1 introductionchoices.cs.illinois.edu/papers/theses/ms.windowingwin32.doc · web viewanother...
TRANSCRIPT
Copyright by Anil Thomas, 1998
THE DESIGN AND IMPLEMENTATIONOF A DISTRIBUTED WINDOWING SYSTEM
FOR WIN32 PLATFORMS
BY
ANIL THOMAS
B.Tech., Mangalore University, 1994
THESIS
Submitted in partial fulfillment of the requirements for the degree of Master of Science in Computer Science
in the Graduate College of the University of Illinois at Urbana-Champaign, 1998
Urbana, Illinois
2
To my parents, with love.
3
Acknowledgements
I thank all those who supported me through this effort. I especially thank Professor Roy Campbell
for his technical and financial support and for being an all around swell guy. I am grateful to
Ashish Singhai for acting as an excellent sounding board. Neil Goldman of Information Sciences
Institute was kind enough to share some of his expertise with me. The software was tested over
the Internet with assistance from Indu Mahadevan, Washington State University. Lastly, I thank
Kishore Narasimhan Mandyam, CEO of Ampersand Corporation for getting me interested in
distributed windowing systems.
4
Table of ContentsChapter1
Introduction.....................................................................................................................................1
1.1 Thesis Outline....................................................................................................................1 1.2 A Note to the Reader..........................................................................................................2
2 Background...............................................................................................................................3
2.1 Related Work.....................................................................................................................3 2.1.1 X-Windows............................................................................................................3 2.1.2 ICA........................................................................................................................5 2.1.3 WTS.......................................................................................................................5 2.1.4 VNC.......................................................................................................................6
2.2 Technology Backgrounder.................................................................................................6 2.2.1 RPC........................................................................................................................7 2.2.2 CORBA..................................................................................................................7 2.2.3 ILU.........................................................................................................................8
3 Design.........................................................................................................................................9
3.1 Design Goals......................................................................................................................9 3.2 Architecture........................................................................................................................9
4 Implementation.......................................................................................................................12
4.1 Intercepting Function Calls..............................................................................................12 4.2 Redirecting Function Calls...............................................................................................16
4.2.1 Replicated GUI Distribution................................................................................17 4.2.2 Non-replicated GUI Distribution.........................................................................17
4.3 Evolution of the System...................................................................................................18 4.4 Issues Encountered...........................................................................................................21
4.4.1 Intercepted Functions...........................................................................................21 4.4.2 Redirected Functions...........................................................................................21 4.4.3 Type of Parameters..............................................................................................22 4.4.4 Handling Resources.............................................................................................22 4.4.5 Processing Events................................................................................................23 4.4.6 Remote Execution................................................................................................25 4.4.7 Web Enabling the System....................................................................................25
5 Results......................................................................................................................................27
5.1 Outcome...........................................................................................................................27 5.2 Performance Evaluation...................................................................................................29
6 Extensions................................................................................................................................34
6.1 Applications.....................................................................................................................34 6.2 Optimizations...................................................................................................................35
7 Conclusion...............................................................................................................................38
5
Bibliography..................................................................................................................................39
Appendix
A Definition Files for the Interceptor DLLs................................................................................42
B Interface Definition for the Redirector.....................................................................................46
6
List of Figures
2.1: The X window system........................................................................................................4
3.1: System components and interaction between them..........................................................10
4.1: Redirecting API function calls.........................................................................................164.2: The application used to test the initial version of the system...........................................194.3: Event handling and callback functions.............................................................................244.4: The complete system configured for use on the Web......................................................26
5.1: Applications running on the final system.........................................................................285.2: Test setup used for performance evaluation.....................................................................295.3: Screenshot of randobj.exe................................................................................................305.4: Network traffic produced by randobj.exe running on Terminal Server...........................315.5: Network traffic produced by randobj.exe running on VNC…...………………………..315.6: Network traffic produced by winmine.exe running on Terminal Server.........................325.7: Network traffic produced by winmine.exe running on VNC...........................................325.8: Comparison of peak network traffic.................................................................................33
6.1: Synchronous RPC vs. Asynchronous RPC......................................................................36
7
Chapter 1
Introduction
Distributed windowing systems enable users to locally interact with programs running remotely.
The X Window system born in 1984 at the Massachusetts Institute Technology is a prime
example for such a system[1]. While X enjoys widespread support in the UNIX community,
Microsoft and Apple chose not to implement distributed computing capabilities in their popular
windowing systems. This left users handicapped by restricting them to using local programs only.
Several attempts have been made to remedy this shortcoming. Among them is a host of
Remote Control applications that let the user control a PC from a remote location. The usefulness
of such software is limited because they allow only one user at a time. Multi-user solutions
include WinFrame from Citrix Systems[2] and Windows Terminal Server (WTS) from
Microsoft[3]. These products work at a device driver level and result in substantial network
traffic. This treatise focuses on the design and implementation of an alternative scheme that
partitions programs at a higher level.
This novel approach involves intercepting function calls and redirecting them to a remote
location where the user interface is displayed. The software was implemented for Win32
platforms. It enables users to partition Win32 applications in such a way that the user interface is
de-coupled from the rest of the logic and can be executed on a different machine. The issues
involved in forcibly partitioning monolithic applications at the API layer are discussed. The thesis
also describes how this technology can be adapted to deploy applications on the World Wide
Web.
1.1 Thesis Outline
The rest of this thesis is organized into chapters as follows:
8
2. Background
This chapter discusses similar work done elsewhere and also gives an overview
of technical concepts used in the implementation.
3. Design
A high level description of the system and its architecture.
4. Implementation
A detailed description of how the system was built to meet the objectives.
Enumerates and discusses the issues faced during the implementation stage.
5. Results
Observations on the end product. Performance evaluation is also documented in
this chapter.
6. Extensions
This chapter discusses various applications of the system and also a few possible
improvements.
7. Conclusion
A summation of the entire project.
1.2 A Note to the Reader
The notion of client and server in X protocol terminology is the opposite of that held
conventionally. To avoid confusion, the author has limited the usage of these words and used
host and terminal instead. The host is the machine that hosts applications and the terminal is
where the GUI is displayed. The terminal corresponds to an X server in X terminology.
9
Chapter 2
Background
This chapter covers background information such as similar work done elsewhere and various
technological concepts used to implement the system.
2.1 Related Work
This section gives an overview of conceptually similar projects. Distributed windowing systems
such as X Windows, ICA and WTS are discussed.
2.1.1 X-Windows
X has been accepted as ‘the’ windowing system for workstations, minicomputers, mainframes
and supercomputers. X began in 1984 at the Massachusetts Institute of Technology as a joint
project between the Laboratory for Computer Science and Project Athena with much of the early
work sponsored by DEC and IBM[4].
The X system consists of three main parts:
1. The server – the software that controls the user’s display, including the screen, keyboard
and mouse.
2. The clients – the application programs, which are completely separate from the server.
3. A communications link, which connects the clients and the server.
The client is the actual application. Whenever an application wants to render data on the screen or
make a change to the visual interface, it sends a request to the server. Examples of requests are to
create windows on the screen, to change the size or location of windows and to draw text or
graphics on these windows. The server accepts these requests and does the required processing.
Another function of the server is to notify the client about user events. It does so by sending
10
events across the communications link telling them about input from the keyboard or mouse, or
indicating certain changes in the status of windows.
Figure 2.1: The X window system.
The X Window System differs from Microsoft windowing systems and Macintosh in the
following aspects.
X is a client/server windowing system. Applications running on one machine can use the
display of another.
X is not a part of the operating system.
The user interface is not built into the base X system.
The X-windows API was designed specifically for a distributed windowing system. X-
Windows applications cannot interact with the display directly. Applications have to send
requests to the X-Server to display anything on the screen. This ensures that the display and its
clients are effectively de-coupled. The flip side is that it makes X comparatively inefficient. Even
while running locally, clients have to request the server to update the display and this involves an
overhead.
The clients transmit most of the requests to the X-server asynchronously and the server
does not acknowledge the requests. So after the client sends one request it doesn't have to wait for
a reply but can send the next request immediately. The effect of this is good utilization of
network bandwidth. Because the client can push requests to the network as fast as it can generate
X ServerApplication Requests
Events
Screen
KeyboardMouse
11
them, there are no occasions when the network is idle because the client is waiting for a response
from the server. Similarly, the server sends events to the client asynchronously.
Another feature of X that helps to minimize network traffic is selective event handling.
Clients have to specify explicitly to the server the types of events it wants to be informed of, and
in which windows. The server will send only these specific events to the client. This feature
avoids unnecessary network traffic and also ensures that clients do not waste time in processing
events that are not of any consequence.
2.1.2 ICA
ICA (Independent Computing Architecture) is the presentation protocol used by WinFrame
from Citrix Systems[2]. WinFrame is a multi-user Windows application server based on
Windows NT under license from Microsoft that supports enterprise application deployment using
a thin-client architecture.
The key to this thin-client architecture is ICA. Along with a data protocol called thinwire,
it specifies how the user interface of applications is captured, transported and reproduced. ICA is
a physical protocol that takes care of lower level network issues such as reliability and
sequencing packets. The thinwire stream is constructed by encapsulating data in ICA packets.
The thinwire component operates at a device driver level. It turns each call to the display driver
into a set of optimized drawing primitives. These primitives are encapsulated into an ICA packet
and passed through a set of protocol drivers that provide functionality like encryption,
compression and framing. This packet is then sent to the client where it passes through the same
layers in the opposite order. This results in the user interface of the application being reproduced
on the client side.
2.1.3 WTS
12
WTS (Windows Terminal Server) is an add-on that provides distributed computing capabilities to
the Windows NT operating system[5]. The components of this system include the multi-user core
of Windows NT, the Remote Desktop Protocol (RDP) and the thin-client software.
The multi-user core provides the ability to support multiple, simultaneous client sessions.
The protocol, RDP is based on International Telecommunications Union’s (ITU) T.120 protocol,
a multichannel conferencing protocol currently used in the Microsoft NetMeeting.
RDP makes use of a special display driver, which gets loaded for remote sessions. All the
information passed by the GDI layer is transferred to the remote client where it is used to produce
the user interface. RDP also takes care of the user events that have to travel in the reverse
direction. The current implementation of RDP runs over TCP/IP.
WTS can optionally use ICA instead of RDP.
2.1.4 VNC
VNC (Virtual Network Computing) is a remote display system developed by the Olivetti &
Oracle Research Laboratories [7]. It is a remote control software that makes it possible to access
the desktop of a remote machine from a variety of machine architectures.
The VNC protocol is based on the concept of a remote frame buffer or RFB. The protocol
simply allows a server to update the screen buffer of a remote client. Because it works at the
framebuffer level, it is potentially applicable to all kinds of windowing systems and operating
systems. The display part of the protocol is based on a single graphics primitive, which manifests
a rectangle of pixel data at given co-ordinates. Updates are sent to the clients only on request.
Input events are sent to the server by the client whenever the user presses a key or pointer button,
or whenever the pointing device is moved.
2.2 Technology Backgrounder
13
Our windowing system makes use of several technology paradigms. An introduction to concepts
such as RPC and CORBA is given in this section. Also included is an overview of the ILU
system from Xerox PARC.
14
2.2.1 RPC
Remote Procedure Calling provides a mechanism for a service to publish a set of operations that
can be used by remote clients[8]. Clients invoke service operations by sending request messages
to the servers. These messages can be sent either synchronously or asynchronously[9]. If the
messages are sent synchronously the client has to wait for a reply from the server before
proceeding. Asynchronous RPC allows sending messages as and when they are generated without
waiting for acknowledgements.
The remote procedure call is modeled on the local procedure call making it usable with
conventional programming languages in a convenient way. An RPC server can be viewed as a
software module, that exports a particular interface which can be made use of remotely.
Normally, a server process is implemented as a daemon that constantly waits for requests from
potentially multiple clients.
The implementation of RPC requires an interface compiler, a communication handler and
a binding service. The interface compiler is used to generate the software components necessary
to implement remote procedure calling transparent to the client program. The interface of the
server module is specified using an interface definition language. The communication handling is
usually done by some form of request-reply protocol. Binding provides a way to establish an
identity for the server modules.
Widely used RPC implementations include Open Network Computing (ONC) RPC from
Sun Microsystems[10] and Distributed Computing Environment (DCE) from Open Software
Foundation (OSF)[11].
2.2.2 CORBA
The Common Object Request Broker Architecture (CORBA) is an interoperability standard that
allows applications to communicate with one another regardless of where they are located[12].
CORBA helps users gain access to data and services transparently without them having to know
15
about which software or hardware platform they reside in or their location on the network. Any
specific implementation of this standard is called an ORB (Object Request Broker). The ORB is
the middleware that makes communication between client and server objects possible. Typically
the protocol used by distributed applications depends on a lot of factors like implementation
language, network transport and way of defining interfaces. ORBs simplify this by defining the
protocol through an implementation language-independent specification, the IDL (Interface
Definition Language). ORBs also allow flexibility by letting programmers choose the most
appropriate operating system, execution environment and implementation language for each
component of a system.
CORBA 2.0 specification from OMG (Object Management Group) defines true
interoperability by specifying how different ORBs can interoperate.
2.2.3 ILU
The Inter-Language Unification system (ILU) is a multi-language object interface system from
Xerox PARC[13]. ILU provides support for building distributed applications. It includes a self-
contained implementation of ONC RPC. It also supports the use of OMG IDL to define object
interfaces and can be thought of as a partially compliant ORB system.
The object interfaces provided by ILU hide implementation distinctions between different
languages, between different address spaces, and between operating system types. ILU interfaces
can be specified in either OMG IDL or ILU’s Interface Specification Language (ISL).
16
Chapter 3
Design
The system was designed keeping in mind a set of objectives. This chapter discusses these goals
and the different modules in the system.
3.1 Design Goals
The primary requirement was that the system needed to be a non kernel-modifying solution. We
did not want any modifications to the operating system because we were dealing with proprietary
operating systems like Windows NT and Windows 95.
We wanted a multi-user system allowing multiple users to access the applications on the
host simultaneously. The system needed to be Internet-ready allowing application delivery on the
Web as transparently as possible.
There were stipulations on the expected performance in terms of network bandwidth
required and latency. The system had to be practicable for use over the Internet. This required that
we minimize the network traffic as much as possible. At the same time, the latency had to be kept
low so that user events are reflected on the display without any uncomfortable delay.
The architecture needed to be thin-client, thereby effortlessly lending itself to network
computing. Other requirements included scalability and generality. The design was expected to
work for all applications on a chosen platform. Although the implementation was not required to
be complete, we had to make sure that the architecture would scale to accommodate the entire
range of applications. The design was also expected to lead to a common implementation for all
Win32 platforms, viz. Windows NT, Windows 95 and Windows 98.
3.2 Architecture
17
Various components that make up the system are depicted in Figure 3.1.
Figure 3.1: System components and interaction between them.
HostApplication
Interceptor
Redirector Event Dispatcher
Terminal
Terminal Server
Starter
API Function Server Event Handler
Starts up the application
USER and GDI calls
Redirects USER and GDI calls Sends events back Requests for application to be run
Dispatches events
18
The Starter is a daemon that runs on the host waiting for requests from clients to run
applications. As soon as an application is started, the Interceptor kicks in and passes all user
interface API function calls to the Redirector. The Redirector routes these calls to the terminal.
The Terminal Server is the module that takes care of displaying the GUI and trapping events on
the client machine. The API Function Server receives the redirected calls and executes them to
produce the user interface on the screen. The Event Handler is responsible for trapping events
and passing them back to the host machine. The Event Dispatcher replays these events on the
application.
19
Chapter 4
Implementation
The implementation of the system went through several iterations. This chapter describes these
stages in detail. Several issues encountered during implementation are also discussed.
4.1 Intercepting Function Calls
The Win32 user interface API was not designed to be used in a distributed fashion. Since we
were interested in forcibly partitioning applications to run in a distributed environment, the first
requirement was an API capturing mechanism. i.e. a scheme that would allow us to intercept
Win32 API calls, access the parameters and return responses to the caller. The requirements for
this system were laid out as follows,
1. Applicability: The system should not require modifications to source or object code. This
is a requirement because as a generic solution it should work with off-the-shelf
applications. However modification of the executable file itself is allowed.
2. Generality: It should work with Windows NT and 95. Again, our aim was to make the
solution as generic as possible. Since both Windows NT and 95 use a common API, it
made sense to have a common solution that works for both.
3. Completeness: It should be able to intercept all the calls made to user32 and gdi32 DLLs
by a specific application whether direct or indirect. However, calls within and between
functions in user32 and gdi32 can be left out. This is because it is sufficient to trap and
redirect a high level API function to trigger off all the lower level API functions called by
it.
4. Noninterference: The system should not affect the performance of other applications that
may be running on the same machine. The system should be capable of being employed
20
on an individual basis without interfering with either the operating system or other
application programs.
An intercepting system has to insert itself into the flow of control of application programs.
The system should get control whenever an API call is issued and before the target of the call is
reached. The control is handed back to the caller after the intended processing is done. (In our
case the original target is never reached; but the caller is fooled into believing that the response it
gets back is from the original target). Numerous schemes were investigated to achieve this.
The simplest mechanism is the one commonly used by profilers such as APF32CVT. For
each DLL whose functions are to be intercepted, a custom DLL is made with the same exported
interface. As long as we keep the names and ordinal numbers same as the original, it is possible
to make the program dynamically bind to the custom DLL. This is achieved by modifying the
executable file. The net effect is the same as linking the program with a custom import library
that exports the same interface as the one we want to replace. Care has to be taken to have
identical function signatures and to return appropriate values so that undesirable effects are
avoided during run-time.
Another approach is to modify the prologue code of each API function to transfer control
to the interceptor. This can be achieved by inserting JMP or CALL instructions with appropriate
operands at the start of the function. In this case, the target is modified to alter the flow of control.
The image of the DLL in the memory is modified and this requires that the interceptor run in the
same process context as the application.
A third approach is to modify the calls to the API functions as described in Matt Pietrek’s
‘Windows 95 System Programming Secrets’[29]. This works by finding CALLs to the API
functions and modify the CALL to point to the interceptor program. The spy program will need to
be implemented as a DLL and will have to be injected into the address space of the process being
spied on. In Win32 applications all calls to a given API function end up traveling through the
same spot in the executable file. Each CALL instruction to this spot results in a JMP to a
21
particular location in the import function table. By patching that one location to point at the spy
program, you intercept all calls made by the EXE to that function. Now, the problem boils down
to finding these locations that the JMP points to. The import function table typically resides in the
.idata section of each executable. The linker fills this table with dummy addresses during link
time and the Win32 loader patches the table with actual addresses during loading. The spy
program can intercept calls by merely overwriting this table with its own routines.
The first approach was chosen in the final implementation by virtue of its simplicity and
fair conformance to the design requirements. The only requirement that is violated is that of
completeness. If a program uses ‘dynamic dynamic binding’ to call an API function, it would be
impossible to intercept with this mechanism. i.e. Using LoadLibrary() and GetProcAddress() to
call a function would defeat the system. The system would also fail if user32 and gdi32 libraries
are statically linked to the application. But the probability of a program doing either of these is
practically nil. At a later stage if it becomes inadequate, it can be replaced by any of the other
schemes without significantly affecting the rest of the software.
Two DLLs were developed to substitute for user32 and gdi32 DLLs. These DLLs called
xser32 and xdi32 respectively export the same API as user32 and gdi32 with the same ordinal
numbers. For a specific application, it is sufficient to provide only those API functions that it is
statically seen to import. Therefore, it was decided not to implement the complete set of API
functions. A number of Win32 applications were examined with the EXEHDR utility to
determine the functions they import. Based on thus collected statistical data, a subset of
commonly used functions was chosen. Another criterion was that the chosen API should be
sufficient to partition at least one off-the-shelf application for demonstration purposes.
Winmin.exe was chosen for this intent and it was examined to determine the functions imported.
The set of API functions finally selected are given in the definition files of the DLLs (Appendix
A).
22
Each of these functions was implemented in such a way that they can be executed on a
remote machine. They can also be parameterized as a whole to force redirection to a particular
machine. (Remoting is described in detail in section 4.2) . All of them (except variable argument
functions) use the Pascal calling convention (__stdcall) where the callee pops the stack. This is
required so that they can be called just like Win32 API. Variable argument functions such as
wsprintf uses the C calling convention (__cdecl).
The other problem that we faced was how to make applications dynamically bind to these
custom DLLs instead of the system DLLs. A simple-minded solution would be to call these DLLs
user32.dll and gdi32.dll and put them in the directory from which the application is loaded. It
would seem that the loader would see these DLLs before it hits the actual DLLs because the order
of search is
1. The directory from which the application loaded.
2. The current directory.
3. The Windows system directories
4. The Windows directory.
5. The directories listed in the PATH environment variable.
But this scheme will not work because user32.dll and gdi32.dll are mapped into the
memory as soon as the OS boots up. Since the code inside dynamic link libraries is shared
between all applications, they are not loaded again. Of course, we could replace the actual
user32.dll and gdi32.dll with our custom DLLs. But this is as good as placing a system-wide hook
and goes against the design requirement of noninterference. We do not want to remote the entire
desktop but only specific applications.
The solution is to modify the executable file image to make it link to the interceptor
DLLs. This is easier than it sounds because the link happens to be a text string. We can just do a
global search for user32.dll and gdi32.dll and replace them with xser32.dll and xdi32.dll
23
respectively. When the application is run, the loader maps xser32.dll and xdi32.dll into its virtual
address space and patches all the user interface API calls to point to these DLLs.
Another complication arises with indirect dynamic linking. If an application X
dynamically links to DLL Y and DLL Y dynamically links to user32.dll or gdi32.dll, the user
interface API calls will not be trapped. Fortunately, there is a simple work-around. We can make
a DLL Y' by modifying DLL Y in such a way that it dynamically links to xser32.dll and
gdi32.dll. Then we modify the executable X so that it links to Y' instead of Y. e.g. notepad.exe
uses comdlg32.dll which in turns uses user32.dll. We can intercept the indirect calls to user32.dll
by making a DLL xomdlg32.dll that links to xser32.dll and making notepad.exe link with
xomdlg32.dll. Clearly, this would work for any depth of indirection.
4.2 Redirecting Function Calls
The next step in remoting the interface was to redirect the API calls. As can be seen, this fits
neatly into the Remote Procedure Call paradigm. Whenever an API function call is intercepted,
we need to marshal the parameters and send them to the RPC server that is running at the
terminal. The parameters are unmarshalled at the terminal and the same API call is made with the
same parameters (with a few exceptions discussed later). The result of this call is transmitted
back to the host and returned to the caller of the function.
Figure 4.1: Redirecting API function calls.
Redirector
APIFunc (args)
RemoteAPIFuncStub (args)
API Function Server
RemoteAPIFuncImpl (args)
APIFunc (args)
24
4.2.1 Replicated GUI Distribution
After the remote call returns, we have the option of calling the original API function on the host
machine. In this case, the application is not truly distributed. On the host machine, it would run
like an unpartitioned application. But the GUI will show up on the terminal by virtue of
duplication. The return values from the remote procedure calls constitute the state of the
application on the terminal. Since part of this state could be an input to calls that follow, we
require a mapping between these values. Whenever a remote call returns a value, we put it into a
table. Another table is built up with the return values of API functions called locally. There is a
one-to-one mapping between these two tables. Whenever a remote call is to be made, its
parameters are inspected for machine dependency. If a dependency exists, it is substituted with
the corresponding terminal value obtained using the mapping already constructed. The net effect
of doing all this is that the same GUI shows up on both the host and the terminal. For convenient
referring, this method was named replicated GUI distribution.
4.2.2 Non-replicated GUI Distribution
The other option is not to call the function locally. The application will be truly distributed in the
sense that the user interface executes on the terminal and all the rest on the host. The GUI will not
show up on the host. The mapping between return values of local and remote calls is obviated.
Basically, the application program is fooled into believing that the user interface is executing
locally. The resultant behavior is more or less that of X-Windows.
The first method is suitable for collaborative operations such as application sharing. An
application can be shared in such a way that it executes on only one machine but the GUI is
displayed on more than one location. Changes to the display due to some event occurring are
reflected across all screens. Processing user events is simpler because events occurring on a
Terminal can be played back on the host simply by sending this events to the particular window.
In the non-replicated approach, no such window exists on the host and hence playing back of
25
events has to be done by calling the appropriate window callback procedure directly. This leads to
a trade-off in the type of complexity as far as the implementation is concerned. Which method to
choose is largely determined by the intended application domain. The non-replicated method is
more suitable for application delivery across the World Wide Web. Replication would be an
unnecessary overhead in this case and also it would interfere with the display on the host, which
is certainly an undesirable side effect.
4.3 Evolution of the System
The software that we built went through three stages of evolution. Our first attempt was to build
an RPC mechanism from scratch. This was achieved with the help of socket calls to communicate
over the network and simple marshal-unmarshal mechanisms. Replicated GUI distribution was
implemented on top of this. Microsoft Foundation Classes were used for the development. Only a
small set of API functions was implemented in this version. It was tested using a small
application that uses only the API functions in the set. Figure 4.2 shows a screen shot of this
application.
26
Figure 4.2: The application used to test the initial version of the system.
The application responds to user actions by drawing lines or text at random co-ordinates.
The system was tested by running the RPC server on one machine and running the partitioned
application on another. As and when the application was running, all the relevant API function
calls were sent to the RPC server, which executed these calls, thereby reproducing the interface.
Windows messages were trapped by a callback procedure and sent back to the host machine via
socket calls over TCP. On the host machine another program received these messages and sent
them to the actual application. A detailed discussion of how user events are handled appears on
section 4.4.5. The interesting point here is that is was as good as sharing the application between
two users allowing both of them to work on the application simultaneously. The user events
occurring at the host were directly handled by the application and the user events occurring at the
terminal were routed to the host. Whenever the program responded to a user event by calling API
functions, the display was updated on both the machines producing identical displays. However,
we left it as it is and moved on to the next stage because our aim was to suppress the GUI at the
host. Also, many API functions use complex data structures for parameter passing and this called
for a more extensive RPC mechanism.
In the next stage, we graduated to Non-replicated GUI distribution and also decided to
leverage it with an existing RPC library. Microsoft RPC was chosen to implement this version.
Again only a small set of API functions was implemented. The RPC interface was written using
Microsoft IDL. The details are deferred till the next section because most of the concepts are
common to the final implementation. It worked fairly well as a proof of concept; but the non-
availability of source code acted as a deterrent. We wanted to be able to customize the RPC
libraries to improve performance. At this point, we decided to use an ORB for the remote call
mechanism. Using CORBA had other advantages such as replacing the ORB with a different one
with minimal changes to the rest of the system.
27
We first experimented with OmniBroker, a CORBA-2 compliant, free ORB, available
with full source code[30]. The interface was rewritten in OMG IDL and the system was
implemented using C++. It worked as expected; but implementing the system in C++ involved
new challenges. The parameters had to be converted into objects for transfer through the ORB. At
the other end they had to be converted back into their original form that is understood by the API
functions. This involved some overhead, especially for functions with complex parameters. What
we wanted was a lightweight scheme, which also allowed implementation in C. We wanted to
avoid as many overheads as possible because performance was critical in such a system.
Fortunately, the Inter-language Unification system (ILU) from Xerox Corporation had all the
qualities that we were looking for. An overview of the ILU system is given in section 2.2.3.
28
4.4 Issues Encountered
Most of the software had to be rewritten to make it use ILU for the remoting mechanism. The
parts that could be reused were the interceptor and the IDL file. The issues to be resolved in the
final implementation were,
Deciding which functions to intercept.
Deciding which functions to redirect.
Deciding the type of parameters (in, out or inout).
Handling functions with resource identifiers as parameters.
Handling functions with callback functions as parameters and distributing events.
Starting up applications remotely.
Web enabling the system.
4.4.1 Intercepted Functions
The interceptor was extended to take care of many more API functions that are commonly used
by Windows programs. Since our objective was to make it work for at least one off-the-shelf
application, it was decided to implement all the user interface API functions used by a commonly
used program that comes with the operating system. The game Minesweeper was chosen for this
purpose. The interceptor DLLs xser32 and xdi32 were extended to trap all the calls made by
winmine.exe to user32 and gdi32 respectively.
4.4.2 Redirected Functions
Some functions in user32 and gdi32 do not have any visual effect and therefore need not be
redirected. If a function is not redirected, it is called locally and the results returned to the caller.
There is no harm in redirecting all the function calls as far as the correctness of the program is
concerned. However, for optimum performance, unnecessary network communication should be
29
avoided. The rule of thumb used was to redirect all the functions that have either direct or indirect
visual consequence. Direct visual consequence is when a function call results in some visible
change to the screen. Indirect visual consequence means the output (the return value and/or
parameters passed by reference) of a function constitutes part of the input to another function that
has either direct or indirect visual consequence.
e.g. The function LoadBitmap() has indirect visual consequence because its output can be used as
an input to SelectObject() whose output in turn can be used by BitBlt() resulting in visual
modifications to the display.
But there are exceptions such as LoadString() which need not be redirected even though
they have indirect visual consequence. The string loaded by LoadString() is passed by value to
the functions that use it through the RPC mechanism and therefore does not have to be loaded
again at the terminal.
Another way to look at it would be to think of the application as having two contexts.
One is the state of the host machine and another that of the terminal. Let the context at the
terminal be called the visual state. Any function that can potentially change this visual state has to
be redirected. If not, it will result in unnecessarily duplicating part of the state at the host.
4.4.3 Type of Parameters
It turns out that there are no hard and fast rules to determine whether a parameter is in or inout.
Each function was examined to determine whether any of the parameters are used to return the
results. Care was taken not to tag a parameter as out unnecessarily because that would result in
extra data transfer across the wire.
4.4.4 Handling Resources
Some of the API functions take resource (bitmaps, icons, menus, dialog box templates, cursors
etc) identifiers as parameters. Typically, these resources are inside the executable file. Since the
executable file does not exist on the terminal, we have to extract these resources and send them
30
across. We used resource extraction functions provided by Win32 API to do this. The resources
can also be extracted by following the executable format and searching for particular sections. At
the terminal, these resources are received and saved into a dummy executable before the
application starts running. Whenever a function that requires a resource is called, the module
parameter is substituted with the loaded image of this dummy executable. This approach results
in a small delay before the application can be run. Another approach would be to extract the
resources and transfer them only when they are needed. In this case, the application can be started
right away but the performance while usage will suffer. Improvements are discussed in the
optimization section.
4.4.5 Processing Events
Handling user events is directly connected to the way callback functions are dealt with. Whenever
an event occurs its handler is to be called. In our case this becomes complicated because the event
occurs on one machine and the handler resides on another machine. This problem is solved as
described below.
Whenever the application program registers a callback function, the function that does
the registering is remoted to the Terminal. The callback function is entered into a table along with
the window handle. At the Terminal, the callback function is substituted with a generic event
handler. Whenever this particular event occurs, the generic event handler is called. The generic
handler sends this event across the network back to the Host. This event is received by the
interceptor and dispatched to the appropriate event handler. Dispatching is done by looking up the
table of callback functions, using the window handle as the key.
31
Figure 4.3: Event handling and callback functions.
An event is represented by four values; the window handle (hWnd), message type (Msg)
and two message parameters (wParam and lParam). The Dispatcher uses hWnd to decide which
function to call. The mapping between the window handles and callback functions is actually
more complicated than what is depicted in the diagram. A single window can have more than one
Terminal Server
Event Dispatcher
Application
…CALLBACK1
Generic Handler
HWND CALLBACK… …
CALLBACK3CALLBACK2
Event (hWnd, Msg, wParam, lParam)
Sends the event to the Dispatcher via RPC
Calls the appropriate function after looking up the callback function table
32
callback procedure to handle different type of events. In that case the Dispatcher has to check the
message type to disambiguate the callback function. The timer callback function registered by
SetTimer() is an example of this occurrence. After the event is dispatched, the callback function
responds by doing some processing. If this processing involves more USER or GDI calls, they are
redirected to the Terminal as before. The Dispatcher and Redirector execute as separate threads
so that waiting for events does not interfere with redirecting function calls.
4.4.6 Remote Execution
The setup also requires a component that is used to remotely start up applications on the host.
This module called the Starter was implemented to receive requests from the Terminal Server.
Again, the RPC paradigm was used to send these requests across the network. Upon receival of a
request, the starter uses the CreateProcess() API function to execute the application. The Starter is
a daemon, which is presumed to be always running on the host waiting for requests from
Terminal Servers.
4.4.7 Web Enabling the System
Web enabling the system involves making application delivery possible on the Web. The users
must be able to access and execute programs published on Web pages and interact with them. All
the necessary components to achieve this are already in the system. All that needs to be done is
configure the Terminal Server as a helper application to any browser. To publish applications,
make a file corresponding to each program containing its name. When a browser retrieves this
file, it will be passed on to the helper application. The helper application contacts a name server
to find out which machine is hosting the application and requests the Host to run it. The interface
shows up on the terminal as described before.
33
.
Figure 4.4: The complete system configured for use on the Web.
The simple binding service provided by the ILU system was used as the name server. By
default, ILU uses files to publish interfaces. Certain include files had to be modified and the
kernel recompiled to incorporate the change. The location of the name server is hard-coded into
the ILU kernel. But this can be overridden by defining an environment variable as described in
the ILU manual.
Web Browser
Terminal Server
Application
Retrieves document containing embedded application
Publishes and reads interfaces
Web Server
Interceptor
Starter
Requests application
Publishes interface
Reads interface
Name Server
34
Chapter 5
Results5.1 Outcome
A set of applications was chosen to illustrate the operation of the system. The choice was limited
by the number of API functions that were implemented to be remotable. The use of these
programs for benchmarking is questionable. Only two of them are off-the-shelf applications and
the rest were written by us for illustrative purposes. However, these programs act as a good
indicator as to how the system will behave with proper benchmarking programs. A screenshot of
these applications running in a distributed fashion is given in Figure 5.1.
The screenshot shows the entire desktop of SRGPC4 where a Terminal Server is running.
The four applications shown were remotely started on another PC, SRGPC6. The applications
from top to bottom are,
Polybez.exe: GDI example program that draws Bezier curves on a window.
Randobj.exe: GDI example program that continuously draws random objects with random
colors on a window.
Reversi.exe: A software implementation of the game Reversi.
Winmine.exe: Minesweeper game that is shipped with all MS-Windows operating systems.
35
Figure 5.1: Applications running on the final system.
As can be seen from the screenshot, the user interfaces appear as if the programs are
running locally. The user can interact with the user interfaces and they display acceptable
responsiveness. The sample programs were also tested using VNC (a remote control system from
Olivetti Research Laboratory) for comparison purposes. All the applications displayed superior
responsiveness and faster painting running on our system. The improvement was especially
apparent with polybez and randobj, which continuously call a number of GDI functions (20 calls
per second).
36
5.2 Performance Evaluation
Figure 5.2 shows the test setup used.
SRGPC4
Dual-processor Pentium 200MHz128MB RAMMicrosoft Windows NT Server Version 4.0 (Build 1381: Service Pack 3)
NETWORK10 Mbps Ethernet
SRGPC6
Dual-processor Pentium 200MHz128MB RAMMicrosoft Windows NT Server Version 4.0 (Build 1381: Service Pack 3)
Figure 5.2: Test setup used for performance evaluation.
The network traffic was monitored using the Network Monitor Agent available with Windows
NT Server. The number of bytes transferred per second was plotted against time. The charts
produced by randobj.exe are shown in Figure 5.4 and Figure 5.5. The Y-axis is the network
traffic in kilobytes and each division in the X-axis represents a second. The charts were produced
with updates every second.
Figure 5.4 shows the network traffic with randobj.exe running on SRGPC6 and the
Terminal Server on SRGPC4. Figure 5.5 shows the traffic with randobj.exe running on SRGPC6
and VNCViewer on SRGPC4. As can be seen, VNC transfers less number of bytes on an average.
This is contrary to our expectations because VNC transfers the contents of the video memory
across the wire and this is clearly at a lower level than remoting API functions. But a closer
37
inspection of the results reveals the reasons behind this unanticipated behavior. It turns out that
VNC produces less network traffic because it does not faithfully update the screen at the client
side.
The program randobj.exe uses a timer to trigger off GDI calls. The time-out value of this
timer is set as 50 milliseconds which means the program makes 20 GDI calls per second. But the
graph for VNC shows a peak approximately every two seconds. This means it is updating the
screen once in two seconds instead of 20 times in one second. This significantly hampers the
performance of the system and can be observed visually. The Terminal Server produces a smooth
visual effect, which is practically indistinguishable from the program running locally. VNC
results in jerky refreshing as can be deduced from the graphs.
Moreover, VNC uses RRE (rise-and-run-length encoding) to compress the data thereby
reducing the amount of data transferred over the network.
Figure 5.3: Screenshot of randobj.exe.
38
Figure 5.4: Network traffic produced by randobj.exe running on Terminal Server.
39
Figure 5.5 Network traffic produced by randobj.exe running on VNC.
40
Figure 5.6: Network traffic produced by winmine.exe running on Terminal Server.
41
Figure 5.7: Network traffic produced by winmine.exe running on VNC.
Figures 5.6 and 5.7 compare the network traffic for a typical run of Minesweeper. VNC
results in less network traffic even in this case. Additionally, it also displayed superior
responsiveness. This is probably due to the huge number of synchronous RPC calls caused by
Minesweeper when running on our system. However the performance was comparable. The
Terminal Server version also exhibited better cursor tracking.
Another interesting observation is that the peak network traffic is typically greater for
VNC. This is especially true for polybez.exe and randobj.exe. The table in Figure 5.8 shows a
comparison of peak traffic.
Application Peak Network Traffic (bytes/s) Terminal Server VNC
Randobj.exe 44K 105K
Polybez.exe 58K 104K
Reversi.exe 62K 96K
Winmine.exe 96K 98K
Figure 5.8: Comparison of peak network traffic.
It was also observed that VNC causes the network traffic to peak more often than Terminal Server does.
42
Chapter 6
Extensions
6.1 Applications
1. Centralizing application deployment: Applications can be deployed on a central server and
accessed from multiple desktops. This simplifies deployment and slashes maintenance costs.
Software upgrading, troubleshooting and management becomes easier because they can be
done from a single access point to the entire network. Another advantage is, powerful servers
can be used to host applications and less powerful ones can be used as desktop clients
resulting in efficient utilization of available resources.
2. Publishing applications on the Web: As explained in section 4.4.7, this technology can be
used to deliver applications from a Web page. Anybody on the Internet with access to
Terminal Server software will be able to use these applications. This can be especially useful
for evaluation software. The user is saved from the hassles of downloading and installing the
software for evaluation purposes.
3. An alternative to Java applets: This can be achieved simply by having the Terminal Server as
a plug-in to any Web browser. But to make it work on non-Win32 platform a subset of the
Win32 API will have to be emulated.
4. Remote control: A PC can be controlled remotely from any location on the Internet using this
technology. This enables users to access their software and data from a remote location.
5. Network computing: A thin-client device is sufficient to run programs off a central server.
This device needs only the minimum capabilities necessary to communicate over the network
and execute a set of functions. This could even be a Java machine implemented to run a
predetermined subset of Win32 API.
43
6. Generic viewer: Publishing documents on the Web requires a viewer application at the client
side. Typically, the formats not understood by the browser are handled by either a helper
application or a plug-in. It would be possible to have this viewer on the server instead.
Whenever a particular document is requested, this viewer application is launched and its
interface transported to the client side where it is displayed using the Terminal Server
software. Thus it acts as a generic viewer for all kinds of file formats (subject to certain
constraints). The document itself need not be downloaded.
6.2 Optimizations
What has been implemented is a very basic system that is just sufficient to satisfy the objectives
laid out in the beginning. There are a number of optimizations possible to make it perform better.
The optimizations discussed result in reduced network traffic, reduced latency or both.
An obvious way to reduce network traffic is to compress the data before sending it over
the network. The parameters to function calls can be examined to determine their size and see if it
is worthwhile to spend some CPU time in compressing them. There is trade-off between
minimizing the network traffic and the delay involved in compressing the parameters. A
reasonable compromise can be arrived at after taking the available bandwidth and the processor
speed into consideration.
Parameters can be cached at the Terminal so that if another call is made with the same
parameter, it doesn't have to be transferred at all. This requires that the Redirector be aware of
what values are cached by the Terminal Server. It makes sense to do this for large parameters like
bitmaps and large arrays. A variation of this is to cache entire RPC calls so that if the same call is
made with the same parameters, just an identifier can be sent to the Terminal Server.
Implementing on-demand resource retrieval can reduce the start-up time. The current
implementation downloads all the static resources (bitmaps, menus, dialog box templates etc.)
before the application is actually run. Instead, we can retrieve them as and when they are needed.
44
Even though it enables the application to start up immediately, it will slow down the execution of
API functions that use static resources. Another option is to download all the resources using a
background thread and block any function call that needs a resource that has not been
downloaded yet.
Techniques can be borrowed from the X-protocol, to get the maximum performance out
of the system. One possibility is to make asynchronous RPC calls whenever possible. If the return
value of a function is just a success indicator or void, it can be made into a one-way call. Since
the function is assumed to succeed, it raises questions such as what happens if it does not. But
dealing with this additional complexity is definitely worth it because it enables the Redirector to
push functions onto the network as soon as they are generated. This is also applicable to RPC in
the reverse direction that is used to pass events.
Figure 6.1: Synchronous RPC vs. Asynchronous RPC.
F1 F2
F1
F1 travels to server
Server replies
Sever processes F1
F2
45
Even functions that return consequential values can be issued asynchronously. Note that this is
not a one-way call because the return value might be wanted further down the program. All the
functions that use this return value need to be blocked till it arrives. The improvement in
performance will depend on how many calls can be issued without having to wait for a response.
The number of events sent to the Host can be significantly reduced by pruning out events
that are not handled by the application. For example, an event is generated whenever the mouse is
moved and can lead to substantial traffic on the network. But if this event is not handled by the
application, there is no point in sending this event across. Other ways to reduce the number of
events include using local timers instead of remote ones. This can lead to substantial bandwidth
saving because the timer messages (which can occur as frequently as 1000 per one second) will
be generated and handled locally.
46
Chapter 7
Conclusion
Popular windowing systems from Microsoft have been found lacking in distributed computing
capabilities. The demand for an X-windows-like system has been on the rise for the past few
years. This need was partially met by remote control programs and more recently Microsoft’s
Terminal Server Edition of Windows NT 4.0. Our project focused on how an improved
distributed windowing system can be built on top of Win32 operating systems by employing an
alternative scheme.
An experimental system was designed and implemented following a set of goals. The
system required implementing a mechanism to intercept user interface API function calls and
redirecting them to a different machine. Other components of this distributed windowing system
include an event interceptor and dispatcher that are used to process remote user events and a
server module that starts up applications remotely. The system was built in such a way as to make
deployment of applications on the World Wide Web possible. It also allows multiple clients to
access published applications simultaneously. The ILU system from Xerox PARC was used to
implement the RPC layer on top of which the system was built.
The implementation was tested using various benchmarking programs and the
performance evaluated. A comparison study showed that it performed better than existing
solutions in several cases. The implementation is not generic and there are restrictions to the kind
of programs that can be partitioned to run in a distributed environment. Nevertheless, it satisfies
all the objectives that were laid out in the beginning of the project and proves the concept of
partitioning applications at the API level.
47
Bibliography
[1] A. Nye. X Protocol Reference Manual. O'Reilly & Associates, Inc., 1989.
[2] Citrix Systems. ICA Technical Paper. URL - http://www.citrix.com/technology/icatech.htm,
1996.
[3] Microsoft Corporation. Microsoft Windows NT Server 4.0, Terminal Server Edition: An
Architectural Overview. White paper, Jun 1998.
[4] N. Mansfield. The Joy of X. Addison-Wesley Publishing Company, 1993.
[5] Microsoft Corporation. Microsoft Windows NT Server 4.0, Terminal Server Edition:
Bringing Windows to Desktops That Can't Run Windows Today. White paper, Jun 1998.
[6] Microsoft Corporation. Comparing Microsoft Windows NT Server 4.0, Terminal Server
Edition and UNIX Application Deployment Solutions. White paper, Jun 1998.
[7] The Olivetti & Oracle Research Laboratory. Virtual Network Computing. URL -
http://www.orl.co.uk/vnc, 1998.
[8] A.D.Birrell and B.Y.Nelson. Implementing Remote Procedure Calls. ACM Transactions on
Computer Systems, 2(1):39-59, Feb 1984.
[9] G. Coulouris, J. Dollimore and T. Kindberg. Distributed Systems: Concepts and Design.
Addison-Wesley Publishing Company, 1995.
[10 ] SunSoft. Solaris ONC: Design and Implementation of Transport-Independent RPC. Solaris
2.0 White Papers, 1991.
48
[11] Open Software Foundation. OSF DCE 1.0 Application Development Guide. Technical
report, Dec 1991.
[12] J. Siegel. CORBA Fundamentals and Programming. John Wiley & Sons, 1996.
[13] Xerox Corporation. Inter-Language Unification - ILU. URL -
ftp://ftp.parc.xerox.com/pub/ilu/ilu.html, 1998.
[14] Sun Microsystems Inc. Network Programming Guide, Revision A Mar 1990.
[15] S.J. Mullender. Distributed Systems. Addison-Wesley Publishing Company, 1993.
[16] A.D. Birrel, R. Levin, R.M. Needham and M.D. Schroeder. Grapevine: an Exercise in
Distributed Computing. Communications of the ACM, 25(4):260-73, 1982.
[17] B.W. Lampson. Designing a Global Name Service. Proceedings of the 5th ACM Symposium
on Principles of Distributed Computing, 1-10, Aug 1986.
[18] Microsoft Corporation. RPC Programmer's Guide and Reference, 1993.
[19] R. Srinivasan. RPC: Remote Procedure Call Protocol Specification, Version 2. IETF RFC
1831, Aug 1995.
[20] A. Nye. XLib Reference Manual. O'Reilly & Associates, Inc., 1989.
[21] A.S.TanenBaum and S.J. Mullender. An Overview of the Amoeba Distributed Operating
System. ACM Operating System Review, 51-56, Jul 1981.
[22] V.F. Russo. LINK: A Kernel Based Distributed UNIX. M.S. Thesis, University of Illinois at
Urbana-Champaign, Jan 1987.
49
[23] Object Management Group. CORBA 2.2/IIOP Specification, 1998.
[24] D. Schmidt. Overview of CORBA. URL - http://www.cs.wustl.edu/~schmidt/corba-
overview.html, 1998.
[25] S. Vinoski, CORBA:Integrating Diverse Applications Within Distributed Heterogeneous
Environments. IEEE Communications Magazine, Feb 1997.
[26 ] H. Custer. Inside Windows NT. Microsoft Press, Sep 1995.
[27] G. Eddon and H. Eddon. Inside Distributed COM. Microsoft Press, Mar 1998.
[28] C. Petzold. Programming Windows 95. Microsoft Press, Microsoft Press, Mar 1996.
[29] M. Pietrek. Windows 95 System Programming Secrets. IDG Books Worldwide, Inc., 1995.
[30] Object Oriented Concepts, Inc. ORBacus Homepage. URL - http://www.ooc.com/ob, 1998.
[31] B. Zaratian. Microsoft Visual C++ Owner's Manual. Microsoft Press, Apr 1997.
[32] Wine Development HQ. URL - http://www.winehq.com, 1998.
[33] Sun Microsystems. Wabi Software. URL - http://www.sun.com/software/Products/PC-
Integration-products, 1998.
50
Appendix A
Definition Files for the Interceptor DLLs
The .def files for the interceptor DLLs, xser32.dll and xdi32.dll are reproduced in this appendix.
;xser32.def : Declares the module parameters for xser32.dllLIBRARY "xser32"DESCRIPTION 'Win32 Dynamic Link Library'EXPORTS; Function Name Ordinal Number; ------------------ -------------------
AppendMenuW @6BeginPaint @10CheckMenuItem @49ClientToScreen @55CreateWindowExA @85CreateWindowExW @87DefFrameProcA @125DefMDIChildProcA @127DefWindowProcA @128DefWindowProcW @130DialogBoxParamA @143DispatchMessageA @144DispatchMessageW @146DrawTextA @171EnableMenuItem @177EndDialog @181EndPaint @183FillRect @205GetAsyncKeyState @216GetClassLongA @224GetClientRect @229GetDC @239GetDesktopWindow @241GetDialogBaseUnits @242GetDlgItem @244GetDlgItemInt @245GetDlgItemTextA @246GetKeyState @258GetMenu @266GetMessageA @278GetMessageW @282GetSysColor @298GetSystemMenu @300GetSystemMetrics @301GetWindowLongA @315GetWindowLongW @316
51
GetWindowRect @318InflateRect @332InvalidateRect @339IsIconic @357IsZoomed @364KillTimer @366LoadAcceleratorsA @367LoadBitmapA @369LoadCursorA @370LoadCursorW @374LoadIconA @375LoadIconW @376LoadMenuA @383LoadStringA @388LoadStringW @389MessageBoxA @406MessageBoxW @411MoveWindow @414OffsetRect @422PeekMessageA @432PostMessageA @434PostMessageW @435PostQuitMessage @436PtInRect @444RegisterClassA @446RegisterClassW @450ReleaseCapture @461ReleaseDC @462SendMessageA @475SetCapture @484SetCursor @493SetCursorPos @495SetDlgItemInt @498SetDlgItemTextA @499SetFocus @502SetMenu @508SetRect @521SetTimer @535SetWindowLongA @540SetWindowLongW @541SetWindowPos @543SetWindowRgn @544SetWindowTextA @546SetWindowTextW @547ShowCursor @554ShowWindow @557TranslateAcceleratorA @579TranslateMDISysAccel @581TranslateMessage @582UnregisterClassA @590UpdateWindow @593
52
WinHelpA @607wsprintfA @613wsprintfW @616
; gdi32.def : Declares the module parameters for xdi.dll.LIBRARY "xdi32"DESCRIPTION 'Win32 Dynamic Link Library'EXPORTS; Function Name Ordinal Number; ------------------ -------------------
BitBlt @11Chord @15CombineRgn @20CreateCompatibleBitmap @31 CreateCompatibleDC @32CreateDCA @33CreateDiscardableBitmap @39 CreateEllipticRgn @40 CreateFontIndirectW @46 CreatePalette @54CreatePen @56 CreateRectRgn @60CreateSolidBrush @65DeleteDC @68DeleteObject @71Ellipse @76ExtTextOutW @100FillRgn @102GetDeviceCaps @200GetNearestColor @233GetStockObject @251GetTextExtentExPointW @261GetTextExtentPointA @264GetTextExtentPointW @265GetTextMetricsA @268GetWorldTransform @276LineTo @281ModifyWorldTransform @283MoveToEx @284PatBlt @291Pie @293PolyBezier @299Polygon @307Polyline @308RealizePalette @312Rectangle @315RoundRect @323SelectObject @331SelectPalette @332SetBkColor @337
53
SetBkMode @338SetDIBitsToDevice @345SetMapMode @354SetPixel @360SetROP2 @364 SetTextAlign @369 SetTextColor @371SetViewportExtEx @373SetViewportOrgEx @374SetWindowExtEx @377SetWorldTransform @379TextOutA @388
54
Appendix B
Interface Definition for the Redirector
The definition of the object interfaces is given here in ILU Interface Specification Language (ISL).
INTERFACE UserGdi;
TYPE CHAR = SHORT CHARACTER TYPEID "IDL:Hd/CHAR:1.0";TYPE "LONG" = INTEGER TYPEID "IDL:Hd/LONG:1.0";TYPE "SHORT" = SHORT INTEGER TYPEID "IDL:Hd/SHORT:1.0";TYPE BOOL = INTEGER TYPEID "IDL:Hd/BOOL:1.0";TYPE "BYTE" = BYTE TYPEID "IDL:Hd/BYTE:1.0";TYPE FLOAT = SHORT REAL TYPEID "IDL:Hd/FLOAT:1.0";TYPE WCHAR = SHORT CARDINAL TYPEID "IDL:Hd/WCHAR:1.0";TYPE UINT = CARDINAL TYPEID "IDL:Hd/UINT:1.0";TYPE WORD = SHORT CARDINAL TYPEID "IDL:Hd/WORD:1.0";TYPE ATOM = SHORT CARDINAL TYPEID "IDL:Hd/ATOM:1.0";TYPE DWORD = CARDINAL TYPEID "IDL:Hd/DWORD:1.0";TYPE VOID = SHORT CARDINAL TYPEID "IDL:Hd/VOID:1.0";TYPE LPINT = ARRAY OF 1 INTEGER;TYPE PUINT = ARRAY OF 1 CARDINAL;TYPE PBOOL = ARRAY OF 1 BOOL;TYPE LPVOID = VOID TYPEID "IDL:Hd/LPVOID:1.0";TYPE LPWSTR = ilu.CString TYPEID "IDL:Hd/LPWSTR:1.0";TYPE PWSTR = ilu.CString TYPEID "IDL:Hd/PWSTR:1.0";TYPE LPTSTR = ilu.CString TYPEID "IDL:Hd/LPTSTR:1.0";TYPE LPCWSTR = ilu.CString TYPEID "IDL:Hd/LPCWSTR:1.0";TYPE LPCTSTR = ilu.CString TYPEID "IDL:Hd/LPCTSTR:1.0";TYPE LRESULT = "LONG" TYPEID "IDL:Hd/LRESULT:1.0";TYPE WPARAM = UINT TYPEID "IDL:Hd/WPARAM:1.0";TYPE LPARAM = "LONG" TYPEID "IDL:Hd/LPARAM:1.0";TYPE COLORREF = UINT TYPEID "IDL:Hd/COLORREF:1.0";TYPE HANDLE = CARDINAL TYPEID "IDL:Hd/HANDLE:1.0";TYPE HWND = HANDLE TYPEID "IDL:Hd/HWND:1.0";TYPE HICON = HANDLE TYPEID "IDL:Hd/HICON:1.0";TYPE HCURSOR = HANDLE TYPEID "IDL:Hd/HCURSOR:1.0";TYPE HBRUSH = HANDLE TYPEID "IDL:Hd/HBRUSH:1.0";TYPE HPEN = HANDLE TYPEID "IDL:Hd/HPEN:1.0";TYPE HMENU = HANDLE TYPEID "IDL:Hd/HMENU:1.0";TYPE HINSTANCE = HANDLE TYPEID "IDL:Hd/HINSTANCE:1.0";TYPE HDC = HANDLE TYPEID "IDL:Hd/HDC:1.0";TYPE HBITMAP = HANDLE TYPEID "IDL:Hd/HBITMAP:1.0";TYPE HGDIOBJ = HANDLE TYPEID "IDL:Hd/HGDIOBJ:1.0";TYPE HRGN = HANDLE TYPEID "IDL:Hd/HRGN:1.0";TYPE HACCEL = HANDLE TYPEID "IDL:Hd/HACCEL:1.0";
55
TYPE HFONT = HANDLE TYPEID "IDL:Hd/HFONT:1.0";TYPE HPALETTE = HANDLE TYPEID "IDL:Hd/HPALETTE:1.0";TYPE WNDPROC = CARDINAL TYPEID "IDL:Hd/WNDPROC:1.0";TYPE DLGPROC = CARDINAL TYPEID "IDL:Hd/DLGPROC:1.0";TYPE TIMERPROC = CARDINAL TYPEID "IDL:Hd/TIMERPROC:1.0";TYPE FARPROC = CARDINAL TYPEID "IDL:Hd/FARPROC:1.0";TYPE VOIDS = SEQUENCE OF VOID;TYPE BYTE-SEQUENCE = SEQUENCE OF BYTE;TYPE tagWNDCLASS = RECORD
style : UINT,lpfnWndProc : WNDPROC,cbClsExtra : INTEGER,cbWndExtra : INTEGER,hi : HANDLE,hIcn : HICON,hCursr : HCURSOR,hbrBackGround : HBRUSH,lpszMenuName : LPCTSTR,lpszClassName : LPCTSTREND TYPEID "IDL:Hd/tagWNDCLASS:1.0";
TYPE WNDCLASS = tagWNDCLASS TYPEID "IDL:Hd/WNDCLASS:1.0";TYPE tagCLIENTCREATESTRUCT = RECORD
hWindowMenu : HANDLE,idFirstChild : UINTEND TYPEID "IDL:Hd/tagCLIENTCREATESTRUCT:1.0";
TYPE CLIENTCREATESTRUCT = tagCLIENTCREATESTRUCT TYPEID "IDL:Hd/CLIENTCREATESTRUCT:1.0";TYPE LPCLIENTCREATESTRUCT = ARRAY OF 1 tagCLIENTCREATESTRUCT;TYPE tagPOINT = RECORD
x : "LONG",y : "LONG"END TYPEID "IDL:Hd/tagPOINT:1.0";
TYPE POINT = tagPOINT TYPEID "IDL:Hd/POINT:1.0";TYPE PPOINT = ARRAY OF 1 POINT;TYPE NPPOINT = ARRAY OF 1 POINT;TYPE LPPOINT = ARRAY OF 1 POINT;TYPE POINTS = ARRAY OF 4 POINT;TYPE tagSIZE = RECORD
cx : "LONG",cy : "LONG"END TYPEID "IDL:Hd/tagSIZE:1.0";
TYPE SIZE = tagSIZE TYPEID "IDL:Hd/SIZE:1.0";TYPE PSIZE = ARRAY OF 1 SIZE;TYPE LPSIZE = ARRAY OF 1 SIZE;TYPE tagMSG = RECORD
hw : HWND,message : UINT,wp : WPARAM,lp : LPARAM,time : DWORD,pt : POINT
56
END TYPEID "IDL:Hd/tagMSG:1.0";TYPE MSG = tagMSG TYPEID "IDL:Hd/MSG:1.0";TYPE PMSG = ARRAY OF 1 MSG;TYPE NPMSG = ARRAY OF 1 MSG;TYPE LPMSG = ARRAY OF 1 MSG;TYPE tagRECT = RECORD
left : "LONG",right : "LONG",top : "LONG",bottom : "LONG"END TYPEID "IDL:Hd/tagRECT:1.0";
TYPE RECT = tagRECT TYPEID "IDL:Hd/RECT:1.0";TYPE tagDEVMODE = RECORD
dmSpecVersion : WORD,dmDriverVersion : WORDEND TYPEID "IDL:Hd/tagDEVMODE:1.0";
TYPE DEVMODE = tagDEVMODE TYPEID "IDL:Hd/DEVMODE:1.0";TYPE BYTE-ARRAY-32 = ARRAY OF 32 BYTE;TYPE tagPAINTSTRUCT = RECORD
hd : HDC,fErase : BOOL,rcpaint : RECT,fRestore : BOOL,fIncUpdate : BOOL,rgbReserved : BYTE-ARRAY-32END TYPEID "IDL:Hd/tagPAINTSTRUCT:1.0";
TYPE PAINTSTRUCT = tagPAINTSTRUCT TYPEID "IDL:Hd/PAINTSTRUCT:1.0";TYPE LPDEVMODE = ARRAY OF 1 DEVMODE;TYPE LPWNDCLASS = ARRAY OF 1 WNDCLASS;TYPE LPRECT = ARRAY OF 1 RECT;TYPE LPPAINTSTRUCT = ARRAY OF 1 PAINTSTRUCT;TYPE CHAR-ARRAY-LF-FACESIZE = ARRAY OF 32 CHAR;TYPE tagLOGFONTA = RECORD
lfHeight : "LONG",lfWidth : "LONG",lfEscapement : "LONG",lfOrientation : "LONG",lfWeight : "LONG",lfItalic : "BYTE",lfUnderline : "BYTE",lfStrikeOut : "BYTE",lfCharSet : "BYTE",lfOutPrecision : "BYTE",lfClipPrecision : "BYTE",lfQuality : "BYTE",lfPitchAndFamily : "BYTE",lfFaceName : CHAR-ARRAY-LF-FACESIZEEND TYPEID "IDL:Hd/tagLOGFONTA:1.0";
TYPE LOGFONTA = tagLOGFONTA TYPEID "IDL:Hd/LOGFONTA:1.0";TYPE PLOGFONTA = ARRAY OF 1 LOGFONTA;TYPE NPLOGFONTA = ARRAY OF 1 LOGFONTA;
57
TYPE LPLOGFONTA = ARRAY OF 1 LOGFONTA;TYPE AnonType-1- = ARRAY OF 32 WCHAR;TYPE tagLOGFONTW = RECORD
lfHeight : "LONG",lfWidth : "LONG",lfEscapement : "LONG",lfOrientation : "LONG",lfWeight : "LONG",lfItalic : "BYTE",lfUnderline : "BYTE",lfStrikeOut : "BYTE",lfCharSet : "BYTE",lfOutPrecision : "BYTE",lfClipPrecision : "BYTE",lfQuality : "BYTE",lfPitchAndFamily : "BYTE",lfFaceName : AnonType-1-END TYPEID "IDL:Hd/tagLOGFONTW:1.0";
TYPE LOGFONTW = tagLOGFONTW TYPEID "IDL:Hd/LOGFONTW:1.0";TYPE PLOGFONTW = ARRAY OF 1 LOGFONTW;TYPE NPLOGFONTW = ARRAY OF 1 LOGFONTW;TYPE LPLOGFONTW = ARRAY OF 1 LOGFONTW;TYPE LOGFONT = LOGFONTA TYPEID "IDL:Hd/LOGFONT:1.0";TYPE PLOGFONT = PLOGFONTA TYPEID "IDL:Hd/PLOGFONT:1.0";TYPE NPLOGFONT = NPLOGFONTA TYPEID "IDL:Hd/NPLOGFONT:1.0";TYPE LPLOGFONT = LPLOGFONTA TYPEID "IDL:Hd/LPLOGFONT:1.0";TYPE tagBITMAPINFOHEADER = RECORD
biSize : DWORD,biWidth : "LONG",biHeight : "LONG",biPlanes : WORD,biBitCount : WORD,biCompression : DWORD,biSizeImage : DWORD,biXPelsPerMeter : "LONG",biYPelsPerMeter : "LONG",biClrUsed : DWORD,biClrImportant : DWORDEND TYPEID "IDL:Hd/tagBITMAPINFOHEADER:1.0";
TYPE BITMAPINFOHEADER = tagBITMAPINFOHEADER TYPEID "IDL:Hd/BITMAPINFOHEADER:1.0";TYPE LPBITMAPINFOHEADER = ARRAY OF 1 BITMAPINFOHEADER;TYPE PBITMAPINFOHEADER = ARRAY OF 1 BITMAPINFOHEADER;TYPE tagRGBQUAD = RECORD
rgbBlue : "BYTE",rgbGreen : "BYTE",rgbRed : "BYTE",rgbReserved : "BYTE"END TYPEID "IDL:Hd/tagRGBQUAD:1.0";
TYPE RGBQUAD = tagRGBQUAD TYPEID "IDL:Hd/RGBQUAD:1.0";TYPE LPRGBQUAD = ARRAY OF 1 RGBQUAD;
58
TYPE PRGBQUAD = ARRAY OF 1 RGBQUAD;TYPE RGBQUAD-SEQUENCE = SEQUENCE OF RGBQUAD;TYPE tagBITMAPINFO = RECORD
bmiHeader : BITMAPINFOHEADER,bmiColors : RGBQUAD-SEQUENCEEND TYPEID "IDL:Hd/tagBITMAPINFO:1.0";
TYPE BITMAPINFO = tagBITMAPINFO TYPEID "IDL:Hd/BITMAPINFO:1.0";TYPE LPBITMAPINFO = ARRAY OF 1 BITMAPINFO;TYPE PBITMAPINFO = ARRAY OF 1 BITMAPINFO;TYPE tagPALETTEENTRY = RECORD
peRed : "BYTE",peGreen : "BYTE",peBlue : "BYTE",peFlags : "BYTE"END TYPEID "IDL:Hd/tagPALETTEENTRY:1.0";
TYPE PALETTEENTRY = tagPALETTEENTRY TYPEID "IDL:Hd/PALETTEENTRY:1.0";TYPE PPALETTEENTRY = ARRAY OF 1 tagPALETTEENTRY;TYPE LPPALETTEENTRY = ARRAY OF 1 tagPALETTEENTRY;TYPE tagLOGPALETTE = RECORD
palVersion : WORD,palNumEntries : WORD,palPalEntry : PPALETTEENTRYEND TYPEID "IDL:Hd/tagLOGPALETTE:1.0";
TYPE LOGPALETTE = tagLOGPALETTE TYPEID "IDL:Hd/LOGPALETTE:1.0";TYPE PLOGPALETTE = ARRAY OF 1 tagLOGPALETTE;TYPE NPLOGPALETTE = ARRAY OF 1 tagLOGPALETTE;TYPE LPLOGPALETTE = ARRAY OF 1 tagLOGPALETTE;TYPE tagTEXTMETRICA = RECORD
tmHeight : "LONG",tmAscent : "LONG",tmDescent : "LONG",tmInternalLeading : "LONG",tmExternalLeading : "LONG",tmAveCharWidth : "LONG",tmMaxCharWidth : "LONG",tmWeight : "LONG",tmOverhang : "LONG",tmDigitizedAspectX : "LONG",tmDigitizedAspectY : "LONG",tmFirstChar : "BYTE",tmLastChar : "BYTE",tmDefaultChar : "BYTE",tmBreakChar : "BYTE",tmItalic : "BYTE",tmUnderlined : "BYTE",tmStruckOut : "BYTE",tmPitchAndFamily : "BYTE",tmCharSet : "BYTE"END TYPEID "IDL:Hd/tagTEXTMETRICA:1.0";
TYPE TEXTMETRICA = tagTEXTMETRICA TYPEID "IDL:Hd/TEXTMETRICA:1.0";TYPE PTEXTMETRICA = ARRAY OF 1 tagTEXTMETRICA;
59
TYPE NPTEXTMETRICA = ARRAY OF 1 tagTEXTMETRICA;TYPE LPTEXTMETRICA = ARRAY OF 1 tagTEXTMETRICA;TYPE LPTEXTMETRIC = LPTEXTMETRICA TYPEID "IDL:Hd/LPTEXTMETRIC:1.0";TYPE tagXFORM = RECORD
eM11 : FLOAT,eM12 : FLOAT,eM21 : FLOAT,eM22 : FLOAT,eDx : FLOAT,eDy : FLOATEND TYPEID "IDL:Hd/tagXFORM:1.0";
TYPE XFORM = tagXFORM TYPEID "IDL:Hd/XFORM:1.0";TYPE PXFORM = ARRAY OF 1 tagXFORM;TYPE LPXFORM = ARRAY OF 1 tagXFORM;TYPE RemWin = OBJECT OPTIONAL COLLECTIBLE
SUPERTYPES ilu.CORBA-Object END TYPEID "IDL:Hd/RemWin:1.0"METHODS
AppendMenuW (hm : HMENU, uFlags : UINT, uIDNewItem : UINT, lpNewItem : LPCTSTR) : BOOL,BeginPaint (hw : HWND, INOUT lpPaint : LPPAINTSTRUCT) : HDC,CheckMenuItem (hm : HMENU, uIDCheckItem : UINT, uCheck : UINT) : DWORD,
ClientToScreen (hw : HWND, INOUT lpp : LPPOINT) : BOOL,CreateWindowExA (dwExStyle : DWORD, lpClassName : LPCTSTR, lpWindowName : LPCTSTR, dwStyle : DWORD, x : INTEGER, y : INTEGER, nWidth : INTEGER, nHeight : INTEGER, hWndParent : HWND, hm : HMENU, hi : HINSTANCE, lpParam : LPVOID) : HWND,
CreateWindowExW (dwExStyle : DWORD, lpClassName : LPCTSTR, lpWindowName : LPCTSTR, dwStyle : DWORD, x : INTEGER, y : INTEGER, nWidth : INTEGER, nHeight : INTEGER, hWndParent : HWND, hm : HMENU, hi : HINSTANCE, lpParam : LPVOID) : HWND,
DefFrameProcA (hw : HWND, hWndMDIClient : HWND, uMsg : UINT, wp : WPARAM, lp : LPARAM) : LRESULT,
DefMDIChildProcA (hw : HWND, uMsg : UINT, wp : WPARAM, lp : LPARAM) : LRESULT,
DefWindowProcA (hw : HWND, Msg : UINT, wp : WPARAM, lp : LPARAM) : LRESULT,
DefWindowProcW (hw : HWND, Msg : UINT, wp : WPARAM, lp : LPARAM) : LRESULT,
DialogBoxParamA (hi : HINSTANCE, lpTemplateName : LPCTSTR, hWndParent : HWND, lpDialogFunc : DLGPROC, dwInitParam : LPARAM) : INTEGER,
DispatchMessageA (lpm : LPMSG) : "LONG",
60
DispatchMessageW (lpm : LPMSG) : "LONG",DrawTextA (hd : HDC, lpString : LPCTSTR, nCount : INTEGER, lpr : LPRECT, uFormat : UINT) : INTEGER,
EnableMenuItem (hm : HMENU, uIDEnableItem : UINT, uEnable : UINT) : BOOL,
EndDialog (hDlg : HWND, nResult : INTEGER) : BOOL,EndPaint (hw : HWND, lppaint : LPPAINTSTRUCT) : BOOL,FillRect (hd : HDC, lprc : LPRECT, hbr : HBRUSH) : INTEGER,GetAsyncKeyState (vKey : INTEGER) : "SHORT",GetClassLongA (hw : HWND, nIndex : INTEGER) : DWORD,GetClientRect (hw : HWND, INOUT lpr : LPRECT) : BOOL,GetDC (hw : HWND) : HDC,GetDesktopWindow () : HWND,GetDialogBaseUnits () : "LONG",GetDlgItem (hDlg : HWND, nIDDlgItem : INTEGER) : HWND,GetDlgItemInt (hDlg : HWND, nIDDlgItem : INTEGER, INOUT lpTranslated : PBOOL, bSigned : BOOL) : UINT,
GetDlgItemTextA (hDlg : HWND, nIDDlgItem : INTEGER, INOUT lpString : LPTSTR, nMaxCount : INTEGER) : UINT,
GetKeyState (nVirtKey : INTEGER) : "SHORT",GetMenu (hw : HWND) : HMENU,GetMessageA (INOUT lpm : LPMSG, hw : HWND, wMsgFilterMin : UINT, wMsgFilterMax : UINT) : BOOL,
GetMessageW (INOUT lpm : LPMSG, hw : HWND, wMsgFilterMin : UINT, wMsgFilterMax : UINT) : BOOL,
GetSysColor (nIndex : INTEGER) : DWORD,GetSystemMenu (hw : HWND, bRevert : BOOL) : HMENU,GetSystemMetrics (nIndex : INTEGER) : INTEGER,GetWindowLongA (hw : HWND, nIndex : INTEGER) : "LONG",GetWindowLongW (hw : HWND, nIndex : INTEGER) : "LONG",GetWindowRect (hw : HWND, INOUT lpr : LPRECT) : BOOL,InflateRect (lprc : LPRECT, dx : INTEGER, dy : INTEGER) : BOOL,InvalidateRect (hw : HWND, lpr : LPRECT, bErase : BOOL) : BOOL,IsIconic (hw : HWND) : BOOL,IsZoomed (hw : HWND) : BOOL,KillTimer (hw : HWND, uIDEvent : UINT) : BOOL,LoadAcceleratorsA (hi : HINSTANCE, lpTableName : LPCTSTR) : HACCEL,LoadBitmapA1 (hi : HINSTANCE, lpBitmapName : LPCTSTR) : HBITMAP,LoadBitmapA2 (hi : HINSTANCE, lpBitmapName : WORD) : HBITMAP,LoadCursorA1 (hi : HINSTANCE, lpCursorName : LPCTSTR) : HCURSOR,LoadCursorA2 (hi : HINSTANCE, lpCursorName : WORD) : HCURSOR,LoadCursorW1 (hi : HINSTANCE, lpCursorName : LPCTSTR) : HCURSOR,LoadCursorW2 (hi : HINSTANCE, lpCursorName : WORD) : HCURSOR,LoadIconA1 (hi : HINSTANCE, lpIconName : LPCTSTR) : HICON,LoadIconA2 (hi : HINSTANCE, lpIconName : WORD) : HICON,
61
LoadMenuA1 (hi : HINSTANCE, lpMenuName : LPCTSTR) : HMENU,LoadMenuA2 (hi : HINSTANCE, lpMenuName : WORD) : HMENU,LoadStringA (hi : HINSTANCE, uID : UINT, INOUT lpBuffer : LPTSTR, nBufferMax : INTEGER) : INTEGER,
LoadStringW (hi : HINSTANCE, uID : UINT, INOUT lpBuffer : LPTSTR, nBufferMax : INTEGER) : INTEGER,
MessageBoxA (hw : HWND, lpText : LPCTSTR, lpCaption : LPCTSTR, uType : UINT) : INTEGER,
MessageBoxW (hw : HWND, lpText : LPCTSTR, lpCaption : LPCTSTR, uType : UINT) : INTEGER,
MoveWindow (hw : HWND, X : INTEGER, Y : INTEGER, nWidth : INTEGER, nHeight : INTEGER, bRepaint : BOOL) : BOOL,
OffsetRect (lprc : LPRECT, x : INTEGER, y : INTEGER) : BOOL,PeekMessageA (INOUT lpm : LPMSG, hw : HWND, wMsgFilterMin : UINT, wMsgFilterMax : UINT, wRemoveMsg : UINT) : BOOL,
PostMessageA (hw : HWND, Msg : UINT, wp : WPARAM, lp : LPARAM) : BOOL,
PostMessageW (hw : HWND, Msg : UINT, wp : WPARAM, lp : LPARAM) : BOOL,
PostQuitMessage (nExitCode : INTEGER),PtInRect (lprc : LPRECT, pt : POINT) : BOOL,RegisterClassA (lpw : LPWNDCLASS) : ATOM,RegisterClassW (lpw : LPWNDCLASS) : ATOM,ReleaseCapture () : BOOL,ReleaseDC (hw : HWND, hd : HDC) : INTEGER,SendMessageA (hw : HWND, Msg : UINT, wp : WPARAM, lp : LPARAM) : LRESULT,
SetCapture (hw : HWND) : HWND,SetCursor (hcur : HCURSOR) : HCURSOR,SetCursorPos (X : INTEGER, Y : INTEGER) : BOOL,SetDlgItemInt (hDlg : HWND, nIDDlgItem : INTEGER, uValue : UINT, bSigned : BOOL) : BOOL,
SetDlgItemTextA (hDlg : HWND, nIDDlgItem : INTEGER, lpString : LPCTSTR) : BOOL,
SetFocus (hW : HWND) : HWND,SetMenu (hw : HWND, hm : HMENU) : BOOL,SetRect (lprc : LPRECT, xLeft : INTEGER, yTop : INTEGER, xRight : INTEGER, yBottom : INTEGER) : BOOL,
62
SetTimer (hw : HWND, nIDEvent : UINT, uElapse : UINT, lpTimerFunc : TIMERPROC) : UINT,
SetWindowLongW (hw : HWND, nIndex : INTEGER, lNewLong : "LONG") : "LONG",
SetWindowLongA (hw : HWND, nIndex : INTEGER, lNewLong : "LONG") : "LONG",
SetWindowPos (hw : HWND, hwndInsertAfter : HWND, x : INTEGER, y : INTEGER, cx : INTEGER, cy : INTEGER, fuFlags : UINT) : BOOL,
SetWindowRgn (hw : HWND, hr : HRGN, bRedraw : BOOL) : INTEGER,SetWindowTextA (hw : HWND, lpsz : LPCTSTR) : BOOL,SetWindowTextW (hw : HWND, lpsz : LPCTSTR) : BOOL,ShowCursor (bShow : BOOL) : INTEGER,ShowWindow (hw : HWND, nCmdShow : INTEGER) : BOOL,TranslateAcceleratorA (hw : HWND, hAccTable : HACCEL, lpm : LPMSG) : INTEGER,
TranslateMDISysAccel (hw : HWND, lpm : LPMSG) : BOOL,TranslateMessageA (lpm : LPMSG) : BOOL,TranslateMessage (lpm : LPMSG) : BOOL,UnregisterClassA (lpClassName : LPCTSTR, hi : HINSTANCE) : BOOL,UpdateWindow (hw : HWND) : BOOL,wsprintfA (lpOut : LPTSTR, lpFmt : LPCTSTR) : INTEGER,wsprintfW (lpOut : LPTSTR, lpFmt : LPCTSTR) : INTEGER,WinHelpA (hWndMain : HWND, lpszHelp : LPCTSTR, uCommand : UINT, dwData : DWORD) : BOOL,BitBlt (hdcDest : HDC, nXDest : INTEGER, nYDest : INTEGER, nWidth : INTEGER, nHeight : INTEGER, hdcSrc : HDC, nXSrc : INTEGER, nYSrc : INTEGER, dwRop : DWORD) : BOOL,
Chord (hd : HDC, nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER, nXRadial1 : INTEGER, nYRadial1 : INTEGER, nXRadial2 : INTEGER, nYRadial2 : INTEGER) : BOOL,
CombineRgn (hrgnDest : HRGN, hrgnSrc1 : HRGN, hrgnSrc2 : HRGN, fnCombineMode : INTEGER) : INTEGER,
CreateCompatibleBitmap (hd : HDC, nWidth : INTEGER, nHeight : INTEGER) : HBITMAP,
CreateCompatibleDC (hd : HDC) : HDC,CreateDCA (lpszDriver : LPCTSTR, lpszDevice : LPCTSTR, lpszOutput : LPCTSTR, lpInitData : DEVMODE) : HDC,
CreateDiscardableBitmap (hd : HDC, nWidth : INTEGER, nHeight : INTEGER) : HBITMAP,
63
CreateEllipticRgn (nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER) : HRGN,
CreateFontIndirectW (lplf : LPLOGFONT) : HFONT,CreatePalette (lplgpl : LPLOGPALETTE) : HPALETTE,CreatePen (fnPenStyle : INTEGER, nWidth : INTEGER, crColor : COLORREF) : HPEN,
CreateRectRgn (nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER) : HRGN,
CreateSolidBrush (crColor : COLORREF) : HBRUSH,DeleteDC (hd : HDC) : BOOL,DeleteObject (hObject : HGDIOBJ) : BOOL,Ellipse (hd : HDC, nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER) : BOOL,
ExtTextOutW (hd : HDC, X : INTEGER, Y : INTEGER, fuOptions : UINT, lprc : LPRECT, lpString : LPCTSTR, cbCount : UINT, lpDx : LPINT) : BOOL,
FillRgn (hd : HDC, hr : HRGN, hbr : HBRUSH) : BOOL,GetDeviceCaps (hd : HDC, nIndex : INTEGER) : INTEGER,GetNearestColor (hd : HDC, crColor : COLORREF) : COLORREF,GetStockObject (fnObject : INTEGER) : HGDIOBJ,GetTextExtentExPointW (hd : HDC, lpszStr : LPCTSTR, cchString : INTEGER, nMaxExtent : INTEGER, lpnFit : LPINT, alpDx : LPINT, INOUT lps : LPSIZE) : BOOL,
GetTextExtentPointA (hd : HDC, lpString : LPCTSTR, cbString : INTEGER, INOUT lps : LPSIZE) : BOOL,
GetTextExtentPointW (hd : HDC, lpString : LPCTSTR, cbString : INTEGER, INOUT lps : LPSIZE) : BOOL,
GetTextMetricsA (hdc : HDC, INOUT lptm : LPTEXTMETRIC) : BOOL,GetWorldTransform (hdc : HDC, INOUT lpXform : LPXFORM) : BOOL,LineTo (hd : HDC, nXEnd : INTEGER, nYEnd : INTEGER) : BOOL,ModifyWorldTransform (hdc : HDC, lpXform : LPXFORM, iMode : DWORD) : BOOL,
MoveToEx (hd : HDC, X : INTEGER, Y : INTEGER, INOUT lpp : LPPOINT) : BOOL,
PatBlt (hd : HDC, nXLeft : INTEGER, nYLeft : INTEGER, nWidth : INTEGER, nHeight : INTEGER, dwRop : DWORD) : BOOL,
Pie (hd : HDC, nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER, nXRadial1 : INTEGER, nYRadial1 : INTEGER, nXRadial2 : INTEGER, nYRadial2 : INTEGER) : BOOL,
PolyBezier (hd : HDC, lppt : POINTS, cPoints : DWORD) : BOOL,
64
Polygon (hd : HDC, lpp : LPPOINT, nCount : INTEGER) : BOOL,Polyline (hdc : HDC, lppt : LPPOINT, cPoints : INTEGER) : BOOL,RealizePalette (hd : HDC) : UINT,Rectangle (hd : HDC, nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER) : BOOL,
RoundRect (hd : HDC, nLeftRect : INTEGER, nTopRect : INTEGER, nRightRect : INTEGER, nBottomRect : INTEGER, nWidth : INTEGER, nHeight : INTEGER) : BOOL,SelectObject (hd : HDC, hg : HGDIOBJ) : HGDIOBJ,SelectPalette (hd : HDC, hpal : HPALETTE, bForceBackground : BOOL) : HPALETTE,
SetBkColor (hd : HDC, crColor : COLORREF) : COLORREF,SetBkMode (hd : HDC, iBkMode : INTEGER) : INTEGER,SetDIBitsToDevice (hd : HDC, XDest : INTEGER, YDest : INTEGER, dwWidth : DWORD, dwHeight : DWORD, XSrc : INTEGER, YSrc : INTEGER, uStartScan : UINT, cScanLines : UINT, lpvBits : BYTE-SEQUENCE, lpbmi : LPBITMAPINFO, fuColorUse : UINT) : INTEGER,
SetMapMode (hd : HDC, fnMapMode : INTEGER) : INTEGER,SetPixel (hd : HDC, X : INTEGER, Y : INTEGER, crColor : COLORREF) : COLORREF,
SetROP2 (hd : HDC, fnDrawMode : INTEGER) : INTEGER,SetTextAlign (hd : HDC, fMode : UINT) : UINT,SetTextColor (hd : HDC, crColor : COLORREF) : COLORREF,SetViewportOrgEx (hd : HDC, X : INTEGER, Y : INTEGER, INOUT lpp : LPPOINT) : BOOL,
SetViewportExtEx (hd : HDC, nXExtent : INTEGER, nYExtent : INTEGER, INOUT lps : LPSIZE) : BOOL,
SetWindowExtEx (hd : HDC, nXExtent : INTEGER, nYExtent : INTEGER, INOUT lps : LPSIZE) : BOOL,
SetWorldTransform (hdc : HDC, lpXform : LPXFORM) : BOOL,TextOutA (hdc : HDC, nXStart : INTEGER, nYStart : INTEGER, lpString : LPCTSTR, cbString : INTEGER) : BOOL,
ShellAboutA (hWnd : HWND, szApp : LPCTSTR, szOtherStuff : LPCTSTR, hIcon : HICON) : INTEGER
END;TYPE Factory = OBJECT OPTIONAL
SUPERTYPES ilu.CORBA-Object END TYPEID "IDL:Hd/Factory:1.0"METHODS
CreateRemWin () : RemWinEND;
65