| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| %% |
| %% 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} |