| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| %% | |
| %% Written by Michael Veksler. | |
| %% May be freely redistributed as long as this header is unchanged. | |
| %% The file be modified as long as there will be appropriate comment | |
| %% containing the Author and a description. | |
| %% | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| \documentstyle{article} | |
| \renewcommand{\thepage}{} | |
| \newcommand{\Wine}{Wine} | |
| \newcommand{\WINE}{{\em WINdows Emulator}} | |
| \newcommand{\DDE}{{\em Dynamic Data Exchange}} | |
| \newcommand{\windoz}{MS-Win\-dows} | |
| \newcommand{\fname}[1]{{\tt #1}} | |
| \newcommand{\libwine}{\fname{libwine.a}} | |
| \title{DDE\footnote{DDE is \DDE\ mechanism provided by \windoz. | |
| (Appendix~\protect\ref{sec:DDE}). | |
| } | |
| \ capability for \Wine\footnote{\Wine\ (\WINE) Runs \windoz\ | |
| programs under UNIX\@. (Appendix~\protect\ref{sec:Wine}). | |
| } | |
| } | |
| \author{Michael Veksler 11678223} | |
| %%\date{Aug 6, 1995} | |
| \begin{document} | |
| \maketitle | |
| \vfill | |
| \abstract{\Wine{} provides an environment for running or compiling | |
| \windoz{} applications for UNIX clones (such as Linux). | |
| \Wine{} is not yet finished and lacks many basic important features. | |
| One of the missing features is DDE\@. DDE implementation | |
| (especially for \libwine) requires | |
| UNIX IPC\footnote{IPC - Inter-Process Communication}. This Project | |
| introduces the IPC mechanism into \Wine{}, thus allowing DDE to work | |
| between different \Wine{} processes.} | |
| \vfill | |
| {\LARGE | |
| \begin{itemize} | |
| \item[Instructor:] Avner Lottem | |
| \item[Done for:] Technion- Israel Institute of Technology,\\ | |
| Electrical Engineering software lab$^{\mbox{\small\copyright}}$. | |
| \end{itemize} | |
| } | |
| \vfill | |
| \newpage | |
| \renewcommand{\thepage}{\roman{page}} | |
| \setcounter{page}{1} | |
| \begin{center} | |
| {\LARGE Table Of Contents} | |
| \end{center} | |
| \tableofcontents | |
| \newpage | |
| \renewcommand{\thepage}{\arabic{page}} | |
| \setcounter{page}{1} | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| %% | |
| %% end of title | |
| %% | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| \section{Introduction} | |
| \subsection{The project} | |
| The purpose of the project is to add DDE capabilities into \Wine. | |
| The project enables \Wine{} DDE client-server applications communication. | |
| This involved messing around with: | |
| \begin{itemize} | |
| \item \windoz\ message mechanism. | |
| \item \windoz\ memory management. | |
| \item \windoz\ task management. | |
| \item UNIX messages among \Wine\ processes. | |
| \item Exchanging (sharing) UNIX memory. | |
| \end{itemize} | |
| \subsection{Problem description} | |
| DDE is essentially a communication protocol between \windoz\ | |
| tasks. Implementing this protocol requires communication among | |
| \Wine{} processes and among tasks in one process (each \Wine{} process | |
| can contain several tasks). Since \Wine\ already provides | |
| communication among internal tasks, this project provides communication | |
| between \Wine\ processes. | |
| Different \Wine\ processes should be able to send \windoz\ messages | |
| and to pass \windoz\ memory handles. There also has to be a | |
| synchronization mechanism between the processes (\windoz\ applications | |
| make assumptions about task switching - and don't use semaphores, or | |
| any \windoz\ equivalent). | |
| Passing messages is a bit tricky. \windoz\ gives a feedback about the | |
| success of a message (fails if the window does not exist). | |
| In case of SendMessage (see Appendix~\ref{sec:WindozMsg}), the process | |
| will have to halt until the message has been processed. | |
| In case of PostMessage, things are simpler - only the existence of the | |
| recipient has to be checked. | |
| \windoz\ switches tasks only when certain system calls are used (such | |
| as delivering or polling messages). \windoz\ applications rely on this | |
| behavior. The problem arises when two applications run on different | |
| \Wine\ processes. Since UNIX preempts processes there is no guaranty | |
| that the UNIX task will occur at the correct place (in respect of the | |
| application). | |
| One one hand is the need for compatibility (no UNIX ``current'' | |
| execution), and on the other hand is performance and stability. | |
| Another problem is passing handles between \Wine\ processes. \windoz\ | |
| applications pass atoms\footnote{See appendix~\ref{sec:WhatAreAtoms}}, | |
| memory handles and window handles. These handles have to be allocated | |
| globally (in shared memory) or translated on the fly. | |
| If a process dies from ``unnatural causes'' (e.g.\ kill $-9$). It will | |
| leave garbage in memory and other IPC handles will start floating | |
| around. There should be some way to collect this garbage. | |
| \subsection{Solutions} | |
| \label{sec:ProjSolutions} | |
| \Wine\ uses Sys-V IPC mechanism (See | |
| Appendix~\ref{sec:SysV-IPC}). This allows sharing data and passing | |
| data between processes (The alternatives are not that good in that | |
| respect - see Appendix~\ref{DDE-Alternatives}). | |
| The shared data contains only essential information (performance or | |
| compatibility). The minimum is kept on shared memory in order to get | |
| maximum stability (\windoz\ is known as an unstable system, \Wine\ | |
| should not imitate \windoz\ in this respect). | |
| Communications are done by Sys-V messages and UNIX signals (a signal | |
| wakes \Wine\ up and the message passes the data). Sys-V messages are | |
| used for carrying \windoz\ messages, as well as synchronization | |
| information. There are 3 types of messages: sent, posted and ack. | |
| Ack message is used for synchronization as well as for returning error | |
| codes (In case sending/posting messages fail). When a message is sent, | |
| the sending process will block until \Wine's {\em ack}{} message is | |
| received. | |
| Synchronization between \Wine\ processes is divided into 2 categories, | |
| in both cases the sender of a message waits for an ack message: | |
| \begin{enumerate} | |
| \item Sent messages - Wait until the recipient delivers ack message. | |
| (When the recipient finished message processing) | |
| \item Posted message - The recipient will send ack only during | |
| task switching instructions (like PostMessage, GetMessage, Yield, | |
| etc.). This way nothing will be done after PostMessage until it is | |
| safe. | |
| \end{enumerate} | |
| There is no real \Wine\ server. Every \Wine\ process has to handle | |
| it's end. This approach somehow resembles a distributed OS\@. This | |
| introduces some problems (Resources might not be freed in case of a | |
| crash). On the other hand this ``distributed OS'' approach simplifies | |
| installation and use, and improves performance. | |
| Atoms are stored on shared memory, so every two \Wine\ processes will | |
| be in sync in this respect (atom 5 will mean the same on both | |
| processes). Shared memory handles are stored on shared memory as | |
| well. Shared memory handles are not from the same range as local | |
| memory handles (\windoz\ requires an plication to declare about it's | |
| shared memory). Since local memory handles have different range they | |
| can be allocated locally (without any sync requirements - handle x may | |
| appear on 10 different \Wine\ processes and address different data). | |
| Window handles are allocated locally. This approach gives stability, | |
| but window handles are no longer unique (same handle may appear | |
| on different processes). This requires on the fly window handle | |
| translation. When an \windoz\ message is transfered, \Wine\ will | |
| translate any contained window handle. The sender translates the | |
| handle to a global (unique) handle, the receiver translates the global | |
| handle to the local window handle. | |
| Collecting the garbage of dead processes is done in two cases: | |
| \begin{enumerate} | |
| \item When setting up a new \Wine\ process: If no \Wine\ process is | |
| running and shared memory is floating around all the IPC stuff is | |
| deleted. | |
| \item When sending a message: If the recipient is dead it's IPC | |
| handles are deleted. | |
| \end{enumerate} | |
| \section{The software} | |
| \subsection{DDE project structure} | |
| Old \Wine\ functions call the new DDE functions whenever needed. | |
| (e.g.\ when sending a DDE message, the original SendMessage function calls | |
| DDE\_SendMessage). This approach minimizes changes to original \Wine{} | |
| code. The new code was written in C. The new capabilities where written | |
| as much as possible in OOP\footnote{OOP stands for Object Oriented | |
| Programming}{} style. | |
| Currently DDE uses Sys-V IPC mechanism, for it's operation. | |
| \paragraph{Major OOP objects and files:} | |
| \begin{table}[h] | |
| \begin{center} | |
| \leavevmode | |
| \begin{tabular}{|l|p{20em}|} \hline | |
| Object & Description \\ \hline | |
| shm\_block & shared memory block operations. \\ | |
| shm\_main\_block & (derived from shm\_block.) Things all | |
| DDE applications need access to. \\ | |
| shm\_fragment & Allocation of in-block fragments. \\ | |
| shm\_semaph & Semaphore operations. \\ | |
| dde\_proc & Process and DDE message handling. \\ | |
| dde\_mem & Front end of DDE memory handling | |
| (Interface of DDE to outer world). \\ | |
| dde\_atom & Handling global atoms. \\ | |
| bit\_array & Array of bits. It has atomic | |
| operations, so bits can be used instead | |
| of semaphores. \\ \hline | |
| \end{tabular} | |
| \caption{Objects constructing the DDE extension.} | |
| \label{tab:ObjList} | |
| \end{center} | |
| \end{table} | |
| Table~\ref{tab:ObjList}{} lists the objects used in the DDE code. | |
| The following rules apply to objects: | |
| \begin{itemize} | |
| \item Object names that begin with {\em dde\_$\cdots$}{} are the front | |
| end. These objects are working directly with the rest of | |
| \Wine. Objects that start with {\em shm\_$\cdots$}{} are the back | |
| end. These objects provide services for the rest of the | |
| implementation. | |
| \item The objects are stored in file with the same name as the object. | |
| (e.g.\ dde\_mem is stored in dde\_mem.c and dde\_mem.h). | |
| \item For each object there is a test file (that partially tests it). | |
| The name of this file is object's name with the word ``test'' | |
| (e.g.\ dde\_mem object has dde\_mem\_test.c). | |
| \item dde.h file has declarations used by dde\_proc and external DDE | |
| users. | |
| \end{itemize} | |
| \subsection{Major algorithms} | |
| \paragraph{Delivering messages:} | |
| \label{sec:DeliveringMessages} | |
| \windoz\ messages are passed using Sys-V IPC messages. Processing | |
| starts with SendMessage() or PostMessage() \windoz\ system | |
| functions: | |
| \begin{enumerate} | |
| \item SendMessage and PostMessage call the DDE functions (same names | |
| prefixed with DDE\_). If the DDE functions pass, don't go any | |
| further. If it fails try to process the message in the | |
| conventional way. | |
| \item The DDE message functions call DDE\_DoMessage, which is | |
| the main DDE message processing function. From now on there is no | |
| difference between sending and posting messages (from initiator's | |
| point of view). | |
| \item If the message is not a DDE message or the recipient is not | |
| remote, fail and return to original message functions. | |
| \item Bring the message to a format suitable for IPC delivery. The | |
| format includes: | |
| \begin{itemize} | |
| \item message type (sent or posted). | |
| \item Sender window handle (translated to global window id.) | |
| \item Other message ingredients (msg, lParam). | |
| \end{itemize} | |
| \item Deliver the message to every recipients using | |
| DDE\_DoOneMessage. There might be many recipients in case of a | |
| broadcast (when the ``recipient'' window is -1). | |
| \item DDE\_DoOneMessage delivers the message and waits for response. | |
| Fail if timeout is reached. | |
| \end{enumerate} | |
| \paragraph{Receiving messages:} | |
| Messages from other \Wine\ processes are received. Processing start | |
| from DDE\_GetRemoteMessage(): | |
| \begin{enumerate} | |
| \item DDE\_GetRemoteMessage is called whenever wine is going to wait | |
| or receive X-windows message. If wine is sleeping (waiting for X), | |
| it will waken by a SIGUSR2 signal. In this case the handler will | |
| siglongjmp() out of the select() function. | |
| \item If no remote message is pending in the message queue - exit. | |
| (Sys-V message queue holds the remote messages until they are | |
| read). | |
| \item If the message is broadcasted, goto stage~\ref{BroadcastAlgo}. | |
| \item Translate the global window handle of the recipient to local | |
| handle. | |
| \item Do this if the message was sent. Send the message to the | |
| recipient window. Reply with ack to the sender. (Reply with the | |
| return code of the SendMessage function). {\em \bf Return}\ with | |
| positive return value. | |
| \item Post the message. | |
| \item If PostMessage fails - send failing ack message. | |
| \item If PostMessage passes, add the message data into a FIFO\@. This | |
| FIFO contains all messages that have to be acknowledged (who's | |
| sender is waiting for ack). Whenever internal task switch occurs, | |
| a item from this FIFO is popped out and an ack message is sent. | |
| \item \label{BroadcastAlgo} Iterate through the local windows and | |
| deliver the message to every one of them. | |
| \item Send a positive ack message. | |
| \end{enumerate} | |
| \paragraph{Allocating memory:} | |
| Shared memory allocation is divided into two categories: internal wine | |
| and \windoz\ application. The memory used by \windoz\ applications is | |
| allocated in two phases - allocate internal wine, and then prepare all | |
| the stuff needed by \windoz. | |
| The internal allocation (DDE\_malloc): | |
| \begin{enumerate} | |
| \item Try to allocate big enough memory fragment in allocated shared | |
| memory. | |
| \item If fragment could not be allocated, allocate a new shared | |
| memory block. Allocate the memory fragment. | |
| \item Allocate a shared memory handle (call the dde\_alloc\_handle() | |
| function). The allocated handle is from a range used only by | |
| shared memory handles. This allocation function is used only for | |
| shared DDE memory. | |
| \item Write the handle in the data structure. Also write the | |
| relative location of this handle (Pointer location is useless since | |
| it differs from one \Wine\ process to another). | |
| This information is written in the main shared memory block. | |
| \end{enumerate} | |
| When a fragment is allocated, it is removed from the list of free | |
| memory. | |
| Allocation for \windoz\ applications (this is done in GlobalAlloc): | |
| \begin{enumerate} | |
| \item Do the internal allocation (instead of malloc in the local | |
| allocation). | |
| \item Everything else is the same as with local memory. A segment is | |
| allocated for the new memory, and it's data is kept in the data | |
| structure. | |
| \end{enumerate} | |
| \paragraph{Atoms:} | |
| Atoms have pretty simple algorithms operating on them. Since atoms are | |
| supposed to give a unique number for each string - atoms are | |
| implemented as hash tables. The id of the atom is the entry in the | |
| hash table. The disadvantage of this approach is that there is a limit | |
| on the number of atoms, the big advantages are simplicity and | |
| speed. | |
| Since implementing a hash tables is strait forward, I will not | |
| discuss it in depth. This hash table has two hash functions - primary | |
| and secondary. When searching for an item (for deletion, addition, or | |
| a seek) the following steps are taken: | |
| \begin{enumerate} | |
| \item The primary hash function returns the first entry. | |
| \item \label{AtomHashLoop} | |
| If the entry is empty or no unchecked entries {\bf \em fail}. | |
| \item If the entry is correct, {\bf \em success!!!}. | |
| \item Add the result of secondary hash function to the item index. | |
| \item Goto step~\ref{AtomHashLoop}. | |
| \end{enumerate} | |
| \subsection{Major data structures} | |
| There are two kinds of data structure, local and shared. The local | |
| data structures are strait forward and will not be discussed in | |
| detail. | |
| The shared data structures have four level hierarchy. Each level | |
| depend on the other and can not exist without it. Most structures have | |
| much less than four levels. | |
| \paragraph{Level one data structure - the main block:} | |
| This data structure is part of the shm\_main\_block object. It | |
| contains essential information needed by all \Wine\ processes. : | |
| \begin{enumerate} | |
| \item Semaphore identifier used for locking the data structure. | |
| \item A table containing information about \Wine\ processes. | |
| \item Relative pointers to atoms. | |
| \item A table containing window information. | |
| \item Tables with global memory handles. | |
| \end{enumerate} | |
| The first level is allocated and initialized when \Wine\ calls a DDE | |
| function the first time. DDE functions are: global memory allocation, | |
| global atoms or DDE messages. | |
| The first level data structure contains the second level data | |
| structure. | |
| \paragraph{Atom element (level two):} | |
| Each element is allocated dynamically (the size of the string is | |
| unknown). The allocation is gained from the shm\_fragment object (each | |
| atom is an instance of that object). Each atom contains: | |
| \begin{enumerate} | |
| \item Count of links. Each allocation of the atom establishes a new | |
| link and each deallocation deletes one link (until all links are | |
| removed). | |
| \item The string of the atom. The string ends with a null character. | |
| \end{enumerate} | |
| \paragraph{Wine processes data (level two):} | |
| (part of the dde\_proc object) : | |
| \begin{enumerate} | |
| \item pid (\Wine\ process id). | |
| \item Message queue id. | |
| \item Semaphore used for locking process's data structure. | |
| \item Sys-V shared memory id of the first block in the chain of | |
| process's blocks. | |
| \end{enumerate} | |
| \paragraph{Window information (level two):} | |
| This is part of the dde\_proc object. The index of array entry | |
| specifies the window handle. Each entry contains: | |
| \begin{enumerate} | |
| \item The process index of the \Wine\ process running this window. | |
| \item The local window handle of this window (remember that each DDE | |
| window has different global and local handles). | |
| \end{enumerate} | |
| \paragraph{Global memory handles (Level two):} | |
| (part of bit\_array and dde\_mem objects): | |
| \begin{enumerate} | |
| \item A bit array contains '1' in every entry that refers to | |
| used global memory handle. | |
| \item Array of handles contains handle data. Each entry refers | |
| to a global memory handle (The index is a function of the | |
| handle). The data includes: 1) Sys-V shared memory handles 2) | |
| offset into the memory block. | |
| \end{enumerate} | |
| \paragraph{Block allocation data structure (Level three):} | |
| This data structure a part of the shm\_block object. It is local to | |
| each shared memory block, so every memory block has it's own data | |
| structure. The shared memory blocks are organized in chains grouped by | |
| processes (each DDE process has one and only one chain): | |
| \begin{enumerate} | |
| \item The id of the next shared memory block in the chain. | |
| \item The size of the block. | |
| \item Number of free bytes in the block. | |
| \item The index of the owner process. | |
| \item The first item in the free list (a linked list of free items). | |
| \end{enumerate} | |
| \paragraph{Fragment allocation (Level four):} | |
| This data is a part of the shm\_fragment object. It is a part of the shared | |
| memory allocation mechanism. Every fragment is a part of shared memory | |
| block. Each fragments contain: | |
| \begin{enumerate} | |
| \item The size of the fragment (for allocating and freeing this | |
| fragment). | |
| \item A union that contains one of: | |
| \begin{itemize} | |
| \item data - if it is allocated. | |
| \item offset of the next free fragment (if it is a member of the | |
| free list). | |
| \end{itemize} | |
| \end{enumerate} | |
| \paragraph{Local reference to global memory:} | |
| Global memory blocks are referenced from local memory. This is used | |
| for storing pointers that refer to the memory block. It contains: | |
| \begin{enumerate} | |
| \item next item in the list. | |
| \item shared memory block id. | |
| \item Owner process. | |
| \item Pointer to the data. | |
| \end{enumerate} | |
| \paragraph{Local mirroring of global handles:} | |
| Global handles require local segments handles (when they are locked). | |
| These segments have to be deleted when the handle is freed. | |
| There is a minimal mirroring of handles in the original tables of | |
| wine, this information is stored the way local handles have always | |
| been stored. | |
| \subsection{Interface and IO} | |
| The DDE section of wine has several interfaces to different entities: | |
| \begin{enumerate} | |
| \item User debug information. | |
| \item Interface between several \Wine\ processes. | |
| \item Interface to the `old' code of \Wine. | |
| \end{enumerate} | |
| \paragraph{User debug information:} | |
| The debug information is written according to \Wine's | |
| conventions. This means that dprintf\_$\cdots$ macros are used to | |
| print the debug information. (These macros allow runtime or compile time | |
| disabling of a any sort of debug information). | |
| In some cases the dprintf\_$\cdots$ macros are not powerful enough. In | |
| those cases the following construct is used instead: | |
| \begin{verbatim} | |
| if (debugging_dde) { | |
| /* print whatever is needed for dde debugging */ | |
| } | |
| \end{verbatim} | |
| \paragraph{Interface between \Wine\ processes:} | |
| The interface between processes includes: | |
| \begin{itemize} | |
| \item Message delivery (see Section~\ref{sec:DeliveringMessages}). | |
| \item Sharing \windoz\ constructs (atoms, memory, window | |
| handles). | |
| \item Synchronization among different \Wine\ processes so it will | |
| appear to a \windoz\ as if there is only one process. | |
| \end{itemize} | |
| \paragraph{Interface to the rest of \Wine:} | |
| Most of the interface has been minimized to an additional few lines in | |
| the original functions. The hook for DDE are in the following | |
| locations: | |
| \begin{itemize} | |
| \item Global atoms functions - these are called directly from | |
| \windoz\ applications. | |
| \item Message delivery - a hook calls the DDE functions from the | |
| original message delivery functions. | |
| \item Initialization - Every PeekMessage() call a DDE function to | |
| check if the current window has DDE management (by sending | |
| a dummy WM\_DDE\_INITIATE message). | |
| \item Waiting on messages - The original code for waiting on X | |
| messages was enhanced to wait on DDE messages as well. This | |
| includes aborting sleeps when SIGUSR2 signal is sent. The actual | |
| test for DDE messages is done in the DDE code. | |
| \end{itemize} | |
| \subsection{Major functions and their role} | |
| \paragraph{Message delivery functions:} | |
| \begin{itemize} | |
| \item DDE\_SendMessage and DDE\_PostMessage - hooks used by original | |
| \Wine's SendMessage and PostMessage. They return true if the | |
| message could be successfully sent to a remote \Wine\ process. | |
| Only in this case SendMessage and PostMessage stop further | |
| processing. | |
| \item DDE\_DoMessage - Try to post or send a message to another | |
| \Wine\ process. This function can do broadcasting as well as | |
| sending. (A message is `broadcasted' if it is delivered to every | |
| window on the system). | |
| \item DDE\_DoOneMessage - Deliver a message to a given wine | |
| {\bf process}. | |
| \item dde\_proc\_send\_ack - Send ack message to \Wine\ | |
| process. The input window handle is used for detecting the | |
| process. | |
| \item get\_ack - wait for ack or timeout. | |
| \end{itemize} | |
| \paragraph{Memory allocation functions:} | |
| \begin{itemize} | |
| \item DDE\_malloc - Allocate a shared memory fragment. This function | |
| also allocates global memory handle. | |
| \item DDE\_GlobalFree - Free a shared memory fragment according to | |
| it's handle. And free the handle. | |
| \item DDE\_SyncHandle - synchronize the global handles mirrored | |
| locally. Delete any outdated handles, or remap reallocated | |
| handles. | |
| \item DDE\_mem\_init - initialize or attach the main shared memory | |
| block, and relevant local data structures. | |
| \item shm\_delete\_all - delete all IPC stuff related to this | |
| process. Kill the main memory block if appropriate. | |
| \end{itemize} | |
| \section{Software testing} | |
| The testing of this module was a substantial part of the | |
| development. Testing revealed bugs just as they where created. | |
| \subsection{Testing methods utilized} | |
| \label{sec:TestMethod} | |
| Two major testing methods where used: | |
| \begin{enumerate} | |
| \item Running DDE \windoz\ applications. The applications used are | |
| DDE demonstration applications. This applications seem to show | |
| precisely what DDE is all about. The applications used where: | |
| ddepop1.exe (server), showpop1.exe (client). These | |
| applications come with \windoz\ programming manual by Charles | |
| Petzold \cite{bib:WinManual}. | |
| \item Running standalone DDE objects linked with a test | |
| object. Every object was tested this way. Some objects had to be | |
| linked with a stub that emulated \Wine's functions. The stub is | |
| pretty poor with dde\_mem object since this object requires hard | |
| to emulate functionalities (things like allocating a segment). | |
| For some objects the coverage seems to be perfect (100\%). For | |
| some object the coverage is poor. The objects with massive stub | |
| usage suffer from this (especially dde\_mem). | |
| \end{enumerate} | |
| \subsection{input for testing} | |
| Most of the testing described in section~\ref{sec:TestMethod} has no | |
| input. Most of the testing knowledge is in the test objects | |
| themselves. There are two exceptions to this rule: | |
| \begin{enumerate} | |
| \item The \windoz\ applications described in | |
| section~\ref{sec:TestMethod} - which are essentially an input to | |
| the software. These applications can't be distributed since it | |
| will be a \copyright{} violation. | |
| \item A trace file which is used for comparing test's output with | |
| the expected trace result. This trace file is used for | |
| shm\_fragment validation. This file is implementation Dependants | |
| and should be updated whenever the object is rewritten. When | |
| updating the trace, it should be inspected manually before it is | |
| released. | |
| \end{enumerate} | |
| \subsection{usage instructions} | |
| \paragraph{Running the DDE applications:} | |
| To test the DDE applications one must run: | |
| \begin{verbatim} | |
| prompt> wine /full-path/ddepop1.exe > /dev/null & | |
| \end{verbatim} | |
| Wait for the server window to pop up (A tiny window should appear at | |
| the lower left corner of your screen). Then activate the client by | |
| typing: | |
| \begin{verbatim} | |
| prompt> wine /full-path/showpop1.exe > /dev/null | |
| \end{verbatim} | |
| The server updates ``USA population'' data every 5 seconds. The client | |
| asks for a hot link (i.e.\ it sends a WM\_DDE\_ADVISE on every | |
| item). From that point on the server updates the client of any | |
| population change. | |
| \paragraph{Running the object tests:} | |
| The {\em run\_tests}{} script is provided to automate the object | |
| tests. Every object test is run and the script checks for results. At | |
| the end the script prints a nice summary table. | |
| Invoking tests outside the {\em run\_tests}{} script is not as simple | |
| as it may look. Every test has differently looking output. | |
| \begin{itemize} | |
| \item dde\_atom\_test - The executable is run. It passes if no | |
| errors are printed at the bottom. | |
| \item dde\_mem\_test - The same as for dde\_atom\_test. | |
| \item shm\_semaph\_test - The same as for dde\_atom\_test. | |
| \item bit\_array\_test - The same as for dde\_atom\_test. | |
| \item shm\_fragment\_test - After the executable is run, the output | |
| has to be compared with TEST\_FRAGMENT.std | |
| \item dde\_proc\_test - This actually runs as a client and as a | |
| server. To activate the server one should write: | |
| \begin{verbatim} | |
| prompt> dde_proc_test 1 > server.log | |
| \end{verbatim} | |
| Then the client has to be activated within five seconds by | |
| writing: | |
| \begin{verbatim} | |
| prompt> dde_proc_test > client.log | |
| \end{verbatim} | |
| The log files should contain: | |
| \begin{description} | |
| \item[server.log:] Should contain traces of received | |
| WM\_DDE\_INITIATE message, and ack sent for it. (Pretty much | |
| the same what {\em run\_tests}{} does). | |
| \item[client.log:] Should contain traces of sending | |
| WM\_DDE\_INITIATE and then receiving an ack message. | |
| \end{description} | |
| No `timeout' traces should be present in the log files. | |
| \end{itemize} | |
| \section{Summary} | |
| \subsection{Software limitations} | |
| \begin{itemize} | |
| \item Only most fundamental memory management functions where | |
| written. This means that the following functions will not work: | |
| \begin{itemize} | |
| \item GlobalReAlloc | |
| \item GlobalSize - two line fix. | |
| \item GlobalFlags - two line fix. | |
| \item LockSegment - two line fix. | |
| \item UnlockSegment - two line fix. | |
| \item GlobalFreeAll - will not free DDE memory. | |
| \item GlobalPageLock - two line fix. | |
| \item GlobalPageUnlock - two line fix. | |
| \item GlobalFix - two line fix. | |
| \item GlobalUnfix - two line fix. | |
| \end{itemize} | |
| \item Non DDE messages to remote windows will not work. This is | |
| currently only a sanity check, it may be removed in the future. | |
| \item Message sending has a timeout limit. This is incompatible with | |
| \windoz. This limit increases stability of a singe \Wine\ process. | |
| \item Synchronization mechanism between wine processes is not | |
| perfect. It was not proved theoretically. I never saw it fail. | |
| \end{itemize} | |
| \subsection{Concluding Remarks} | |
| This extension to \Wine{} enables further development of \windoz\ IPC | |
| support. Things like OLE can be extended using these features - | |
| although some modifications might be inevitable. | |
| The most important contribution of this project is the support for | |
| \libwine{}. Any \windoz\ application compiled under UNIX and linked to | |
| \libwine{} will need the IPC mechanism provided by this project. | |
| During the progress of the project it got a bit outdated. During that | |
| time \Wine{} started to handle tasks internally, so the external IPC | |
| was no longer needed for the emulator configuration of | |
| wine. Nevertheless the support of IPC for \libwine will never | |
| be obsolete. | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| %% | |
| %% Appendixes | |
| %% | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| \clearpage | |
| \appendix | |
| \section{\Wine} | |
| \label{sec:Wine} | |
| \Wine\ stand for {\em WINdows Emulator}. It is an X-windows - UNIX | |
| application (Linux and FreeBSD). \Wine\ emulates \windoz\ environment | |
| for the \windoz\ applications. It has two uses: | |
| \begin{enumerate} | |
| \item Run \windoz\ binary code (compiled under \windoz). | |
| \item To be used as a toolkit for compiling \windoz\ applications | |
| under UNIX. (The \libwine\ library is provided) | |
| \end{enumerate} | |
| For emulation, only Intel-Architecture CPU (386, 486, Pentium) are | |
| supported. \libwine\ Toolkit should run on any platforms, but it was not | |
| tested. \Wine\ is still in alpha state, and does not support all \windoz\ | |
| capabilities yet. | |
| \section{Messages under \windoz} | |
| \label{sec:WindozMsg} | |
| Messages are the means of communication to a user window (from another | |
| window or from \windoz\ itself). | |
| Messages can be delivered in two ways: | |
| \begin{itemize} | |
| \item Messages can be sent. The sent message enters the window handler | |
| asynchronously (The handler may be reentered many times). | |
| A window sending the message waits for the recipient to process | |
| the message and return an exit code. | |
| \item Messages can be posted. The posted message enters a queue, and | |
| it's up to the recipient to process it. If the recipient ignores | |
| it, the message might be eventually sent to the recipient from | |
| WinMain handler. | |
| \end{itemize} | |
| \section{DDE} | |
| \label{sec:DDE} | |
| DDE stands for \DDE\@. DDE is an \windoz\ | |
| protocol used for data exchange between applications. | |
| It has synchronous and asynchronous operation modes. | |
| DDE mechanism is based on messages, atoms | |
| (Section~\ref{sec:WhatAreAtoms}) and shared memory. | |
| DDE applications are divided roughly into two classes: servers AND | |
| clients. Clients have the initiative, they try to connect to the | |
| server. Servers only maintain an existing DDE link. | |
| \subsection{DDE Messages} | |
| \paragraph{DDE message format}: | |
| \label{sec:DDEMessageFormat} | |
| DDE messages contain the following fields. | |
| \begin{description} | |
| \item[wnd] The recipient of this message ($-1$ if every window | |
| should receive). | |
| \item[msg] The ID of the message. | |
| \item[wParam] Who sent this message. | |
| \item[lParam] 32 bit parameter, divided into two 16 bit words. | |
| Usually, the lower 16 bits contain a memory handle. The handle | |
| points to some extra DATA about this message. | |
| \end{description} | |
| \paragraph{Available messages:} | |
| \begin{description} | |
| \item[WM\_DDE\_INITIATE] | |
| This message is sent by the client to the whole ``world''. | |
| {\em lParam}{} contains the two atoms used for passing the topic and | |
| application information. | |
| Every server application checks if this message refers to it | |
| (According to the Application and the Topic atoms). | |
| \item[WM\_DDE\_ACK] | |
| This is a generic response to various events | |
| (one of them is WM\_DDE\_INITIATE). | |
| The low part of {\em lParam}{} passes extra information, such as | |
| success/failure. | |
| \item[WM\_DDE\_TERMINATE] | |
| Kill the DDE link. | |
| \item[WM\_DDE\_ADVISE] | |
| Tell the server to inform the client of any updates. | |
| \item[WM\_DDE\_UNADVISE] | |
| Stop the WM\_DDE\_UNADVISE mode. | |
| \item[WM\_DDE\_DATA] | |
| Transfer data handle (note that the data handle must be globally allocated | |
| with the GMEM\_DDESHARE flag). | |
| \item[WM\_DDE\_REQUEST] | |
| Request a data item from the server. This message is used in a | |
| cold link. {\em lParam}{} contains an atom describing the desired | |
| item, and a WORD describing the wanted data format. | |
| \item[WM\_DDE\_POKE] | |
| The client gives the server new data. | |
| \item[WM\_DDE\_EXECUTE] | |
| The client asks the server to execute a procedure (according to a | |
| command string). | |
| \end{description} | |
| \subsection{Atoms} | |
| \label{sec:WhatAreAtoms} | |
| Atoms are represented by numbers. Every atom maps uniquely to a string | |
| (i.e.\ two atoms can't map to the same string). | |
| There are two types of atoms - local and global. The local are visible | |
| only to the application that created them. Global atoms are seen by all | |
| \windoz\ applications. | |
| Functions: | |
| \begin{description} | |
| \item[AddAtom(str)] create a local atom that maps to ``str''. | |
| If it exists, increment the allocation-counter, | |
| and return the atom. | |
| \item[DeleteAtom(atom)] decrement the allocation-counter. When it | |
| reaches zero the atom, will be deleted. | |
| \item[FindAtom(str)] Find the atom that maps to this string (if exist). | |
| \item[GetAtomName(\ldots)] Find the string that this atom points to. | |
| \end{description} | |
| NOTE: | |
| \begin{description} | |
| \item[Global atoms] Add ``Global'' before the listed names to get Global | |
| atom functions. | |
| \item[Case sensitivity] All atom operations ignore case. | |
| \end{description} | |
| \section{DDE under \Wine\ - Alternatives} | |
| \label{DDE-Alternatives} | |
| There where three possible approaches for this project. I have chosen | |
| System-V IPC, but it can be easily changed. | |
| \subsection{IPC - Inter-Process Communication} | |
| \label{sec:SysV-IPC} | |
| The IPC mechanism was originated from System-V UNIX\@. This mechanism | |
| allows complicate communication between two process (on the same machine). | |
| IPC includes the following capabilities: | |
| \begin{enumerate} | |
| \item Shared Memory (shm) - can be shared among few processes and users. | |
| \item Semaphores (These semaphores allow grouped operations - i.e.\ | |
| operations gathered as an atomic operation). | |
| \item Message Queues (allow few messages at a time). | |
| \end{enumerate} | |
| The advantages of IPC over the other variants are: | |
| \begin{itemize} | |
| \item Memory access speed is good. (after the memory was attached). | |
| \item Easy to block critical code (don't enter critical code from two | |
| processes at the same time) | |
| \end{itemize} | |
| Disadvantages of IPC: | |
| \begin{itemize} | |
| \item Impossible to communicate to other machine. | |
| \item Requires complex mechanism to wait both for X and IPC messages. | |
| \end{itemize} | |
| \subsection{X-Windows Communication mechanisms} | |
| The advantages of X-Windows Communication over the other variants are: | |
| \begin{itemize} | |
| \item Possible to communicate to other machines. | |
| \item No need for additional mechanism that will wait both for X and DDE\@. | |
| \item Many of the required capabilities are already there. | |
| \end{itemize} | |
| Disadvantages of X-windows communication: | |
| \begin{itemize} | |
| \item {\em Slow}\ and complex memory access. | |
| \item May be hard to avoid two applications from entering critical | |
| code at the same time. | |
| \end{itemize} | |
| \subsection{BSD Sockets} | |
| The advantages of Sockets are: | |
| \begin{itemize} | |
| \item Possible to communicate to other machines. | |
| \item No need for complex mechanism that will wait both for X and | |
| DDE\@. (can use one ``select'' on X-windows socket in concert with | |
| the DDE socket). | |
| \end{itemize} | |
| Disadvantages of socket are: | |
| \begin{itemize} | |
| \item {\em Slow}{} and complex memory access. (note that mmap on a | |
| descriptor does not work for Linux 0.99). | |
| \item May be hard to avoid two applications from entering critical | |
| code at the same time. | |
| \end{itemize} | |
| \subsection{Why was it written in C? Pros and cons.} | |
| Advantages of C: | |
| \begin{itemize} | |
| \item History- \Wine{} is already written in C. | |
| \item Portability- not all systems have C++. | |
| \item Speed- C++ sometimes makes it very difficult to write fast code. | |
| \item Maintenance- More programmers know C than C++. | |
| \end{itemize} | |
| Advantages of C++: | |
| \begin{itemize} | |
| \item smaller code - Templates allow Smaller and more readable code. | |
| \item Maintenance - It is easier to add and modify code in C++ (than in C). | |
| \item Verification - Functionality can be verified and debugged for | |
| individual objects. | |
| \end{itemize} | |
| I have decided to use C. Most of C++ advantages can be acquired | |
| by using OOP methodologies. OOP methods that require inline functions | |
| can't be used (without performance impact). GCC supports inline functions, | |
| but this solution is not compatible. | |
| \section{\Wine\ basics} | |
| \subsection{How it runs} | |
| \Wine\ works in the following order: | |
| \begin{enumerate} | |
| \item \Wine\ loads the \windoz\ application into it's memory. | |
| (in the process it, links | |
| DLL's\footnote{DLL (Dynamically Linked Library) is linked on load-time.} | |
| creates 16-bit segments). | |
| \item \windoz\ code is executed. | |
| \end{enumerate} | |
| \section{bibliography} | |
| \begin{thebibliography}{99} | |
| \bibitem{bib:WinManual} Charles Petzold {\em Programming | |
| Windows~3.1}{} - 1992. \\ | |
| On cover: {\em the Microsoft guide to writing applications for | |
| windows~3.1}. \\ | |
| Published by {\em Microsoft press}. | |
| \end{thebibliography} | |
| \newpage | |
| \end{document} |