DOC

DfMirage SDK v1.2

By April Ferguson,2014-02-08 11:14
13 views 0
DfMirage SDK v1.2

DfMirage SDK v1.2 Developer’s Guide

    Introduction

    DfMirage is “cutting edge" video driver mirroring technology for the Windows NT OS family. It is a driver for a virtual video device managed at the DDML level of the graphics system that exactly mirrors the drawing operations of one or more physical display devices. A detailed explanation of how a mirroring video driver works may be found in the Windows DDK. Display mirroring technology is widely employed by remote desktop applications such as: NetMeeting, PC Anywhere, VNC, Webex, etc. Mirroring is a technically superior method when compared to primitive screen grabbing, because it allows the capture of only the minimally updated regions and retrieves the data directly, bypassing the intermediate copy. Using the DfMirage driver solves the problem of reliably and efficiently detecting modified areas on the screen. This driver may be used transparently with office, CAD and other types of business and utility applications. An example is the open-source TightVNC application which uses the DfMirage driver with great success.

    Operating environment and setup

    The DfMirage driver is targeted to the Microsoft Windows NT OS family, which includes Windows NT4, Windows 2000, Windows XP/2003 and future versions of Windows as well. It has been tested on Windows 2000 service packs 0-4, and Windows XP service packs 1 and 2. Windows NT4 service pack 6 is also supported (driver package available upon request). Installation

    To setup the DfMirage driver, run MirageSetup.exe.

    The underlying virtual display device uses plug-n-play technology, so the installation requires no reboot. When the driver is installed, it appears in device manager as shown in the following picture: http://www.demoforge.com/support/dfmirror-devmgr.png

    To ensure that the installation was successfull run dfstudio-mirage.exe (this is a special build of DemoForge Studio 2 which uses DfMirage driver internally) and the press the Record button. You may then locate the file just recorded in your %TEMP% folder. This file may be played back. It is rather large because it contains only raw, uncompressed data. If you compress it using any modern archival software, you will see a considerable difference in size. You may also save the recorded file to DML format to see the image data which has been captured by the mirage driver.

    Uninstallation

    The uninstallation of DfMirage is fully supported. The uninstaller is registered with the “Add/Remove Programs” applet of Control Panel.

    Removing the device is a two-phase process. This is due to shortcomings within the Windows system video port driver. Microsoft has promised to resolve this issue with the release of Windows Vista. When the first phase is finished, the system must be rebooted. The 2nd phase will automatically begin following the reboot, when any member of the local Administrators group logs in. For a more detailed explanation of DfMirage setup considerations see the file “Mirage\Setup\Installer\Guide.en.doc”.

    Operating principles

    The DfMirage driver tracks the minimal areas of screen update and enables the client software to retrieve those updates directly (by means of the screen memory shared between the driver and application). This method provides excellent results in terms of traffic and CPU usage, while still maintaining its ease of use features. The Mirror driver follows the standard bi-component model

    of NT video drivers. That is, it uses miniport and display driver modules. Miniport is a low-level component. It represents a virtual video device. It is loaded by the OS IO manager and remains in memory until the OS is terminated. The miniport device is inaccessible to user-mode code. The display driver is loaded and unloaded on demand by changes in video mode. Basically, when it is loaded and running, video mirroring takes place. The DfMirage driver maps its screen surface into the user-mode application’s virtual memory space. Normally, the format and size of the buffer corresponds exactly to the format and size of the primary screen surface. This is not the case when its color format is overridden (there is available, a registry-based switch for the

    driver to enforce the fixed color depth of the mirrored screen surface). The mapping of memory is performed via a file mapping object (or a “Section” using NT kernel slang). In this way an

    application “sees” everything that’s being drawn on the mirrored screen surface, resulting in the application’s ability to perform a direct copy of the modified screen area. It has but read-only

    access to this buffer.

    The driver provides an application with the ability to retrieve ONLY those areas, which are modified, in spite of this, the entire screen buffer is always available to the application for read access.

    The user-mode application communicates with the DfMirage driver via the ExtEscape()

    Windows API function. ExtEscape serves the role of an extensible escape hatch for the

    Windows GDI as it allows the passing of custom or non-standard requests to the video driver. There are a number of private escape codes defined by DfMirage. Escape function codes and input/output structures are declared in display-esc.h (This is an interface header shared among the driver and application code modules).

    The API

    Following is a brief description of this API:

ESCAPE CODE: dmf_esc_usm_pipe_map

    INPUT: None

    OUTPUT: struct GETCHANGESBUF

    FUNCTION: Creates a mirror screen and updates queue mappings for the calling process.

    RETURN VALUES: If the function succeeds, the return value is greater than zero.

    The buffers are mapped upon receiving this escape request. The output buffer format for the request is GETCHANGESBUF. GETCHANGESBUF::Userbuffer is actually a pointer to the mirror

    screen surface view. GETCHANGESBUF::buffer points to the queue of modified rectangles. The

    screen surface is “top to bottom, so the 1st line of pixels in the screen surface commences with the 1st byte of screen memory. For example, you can address the 2nd line of pixels by adding a fixed positive value (stride, also known as a pitch or delta) to the address of the 1st line. The userbuffer value actually points to the line 0. Surface dimensions correspond to the dimensions of the primary display. The stride of the surface is DWORD-aligned upwards. (The stride is

    calculated as follows: (screen_width*(screen_bits_per_pel>>3)+3)&-4.)

ESCAPE CODE: dmf_esc_usm_pipe_unmap

    INPUT: struct GETCHANGESBUF

    OUTPUT: None

    FUNCTION: Terminates the mappings of the shared memory structures.

    RETURN VALUES: If the function succeeds, the return value is greater than zero.

    There is a reciprocal unmap API - dmf_esc_usm_pipe_unmap. It is recommended that this API be used to terminate the capture under normal conditions. Under abnormal conditions it is best to

    unmap the shared memory buffers by calling UnmapViewOfFile(). The

    dmf_esc_usm_pipe_unmap/UnmapViewOfFile() call should always be accompanied by the DeleteDC() call for a previously-obtained mirror-device DC to release an instance of the driver.

(NOTE: this function is new, available in driver version 1.1+)

    ESCAPE CODE: dmf_esc_qry_ver_info

    INPUT: struct Esc_dmf_Qvi_IN

    OUTPUT: struct Esc_dmf_Qvi_OUT

    FUNCTION: Queries for driver’s version and determines if driver and application

    versions are compatible.

    RETURN VALUES: If the function succeeds, the return value is greater than zero.

    If the function succeeds, this means that driver and application are version compatible.

    In Esc_dmf_Qvi_IN application passes it’s version information. See dmf-proto-version.h: set Esc_dmf_Qvi_IN:: app_actual_version to DMF_PROTO_VER_CURRENT, and

    Esc_dmf_Qvi_IN:: display_minreq_version to DMF_PROTO_VER_MINCOMPAT version

    number constants from SDK version it was built with. In Esc_dmf_Qvi_OUT driver returns

    information about its version. Esc_dmf_Qvi_OUT:: display_actual_version is the driver’s

    version number. Esc_dmf_Qvi_OUT:: app_minreq_version is a minimum application version number which is supported by the driver.

CHANGES_BUF is a circular queue of modified rect records (CHANGES_RECORD) (the current

    capacity setting is 20,000 records, which is normally far more than enough). The structure is

    defined as follows:

    struct CHANGES_RECORD

    {

     ULONG type;

     RECT rect;

     RECT origrect;

     POINT point;

     ULONG color;

     ULONG refcolor;

     }; This definition is governed by historical reasons (legacy software compatibility). Not all fields in

    this structure are actually used with Mirage driver. CHANGES_RECORD:: type takes the following values:

    typedef enum

    {

     dmf_dfo_SCREEN_SCREEN = 11,

     dmf_dfo_BLIT = 12,

     dmf_dfo_TEXTOUT = 18,

     dmf_dfo_Ptr_Engage = 48,

     dmf_dfo_Ptr_Avert = 49,

     dmf_dfn_assert_on = 64,

     dmf_dfn_assert_off = 65,

    } dmf_UpdEvent;

    The actual screen update events are dmf_dfo_SCREEN_SCREEN, dmf_dfo_BLIT,

     Records dmf_dfo_Ptr_Engage and dmf_dfo_Ptr_Avert are mouse pointer dmf_dfo_TEXTOUT.

    status events. Engage shows (“checks”) the pointer in a position specified, whereas Avert hides

    the pointer from screen. Pointer coordinates go through CHANGES_RECORD::point field.

    Records dmf_dfn_assert_on and dmf_dfn_assert_off notify the application about the driver’s status.

dmf_dfo_BLIT event is the most common update event type. dmf_dfo_TEXTOUT is results from

    text output. dmf_dfo_SCREEN_SCREEN is a screen-to-screen copy BitBlt.

    Applications should disregard origrect, color, refcolor fields.

    All update types (range dmf_dfo_SCREEN_SCREEN.. dmf_dfo_TEXTOUT) may ultimately be

    treated as BitBlt. The only relevant and valid field of CHANGES_RECORD is then

    CHANGES_RECORD::rect. It is the screen destination update rectangle (a rectangular boundary of an actual update region) of the above-mentioned graphic operations.

    dmf_dfo_SCREEN_SCREEN event type is supported in Mirage driver version 1.2+. To allow this new event type it must be enabled (see below). dmf_dfo_SCREEN_SCREEN may be used as an

    additional optimization option (it may be useful in cases of window drag, scroll, etc.) In addition to CHANGES_RECORD::rect it has valid CHANGES_RECORD::point field the source point of

    screen copy operation.

    The screen of Mirage driver is not divided into a fixed set of predefined rectangles. The update rectangles are placed, sized and ordered exactly in the same manner that the underlying graphic operations were.

    The update rect coordinates are relative to the driver’s attach point on the desktop. If the driver is

    attached at (0, 0) (as usual), rects are in a desktop coordinate space. The head of the buffer is moved cyclically forward when a newly-modified rect arrives (the queue constantly wraps through its end to the beginning). There is an ever-increasing counter of records: The ULONG

    CHANGES_BUF::counter. Using this counter, one may determine whether there are any newly-modified rects available. When the application detects the newly-modified rectangles, it has an opportunity to retrieve those rectangles directly from the mapped screen buffer memory. The application then makes copies of these modified rects and performs the required process on them (for example, sending them over wire).

    If an application detects that it has lost one or more modified rects, (possible when the system is sorely over-taxed) nothing is really broken. The application should simply skip any unprocessed rects and then perform an update of the entire screen . The entire contents of the modified rects buffer is available for read from the application at any time.

    It is important to understand that shared memory structures remain available to the application despite any change to the video mode when the driver is unloaded completely or just disabled temporarily. The shared memory objects are managed by 2 references: from the driver and from the application. These are unavailable when, and only when, both the driver and application release them. This is by design, to ensure reliability in the case of an unexpected disconnection with the client application. This is why it is important to perform the cleanup before reconnection.

    To start working with the driver, the application must first activate it.

    The driver is set to enabled (“Attach.ToDesktop” value in system registry). The video mode

    change is then performed and the new activation setting for the driver takes effect. When the application is finished with the driver, it is deactivated in a similar manner. The driver will remain active, consuming CPU and memory resources until it is unloaded. An error will not result from an attempt to load or unload the driver more than once. Only one instance of the driver will be loaded globally during a given interactive logon session. While there is no technical limit on the number of applications which may simultaneously read the mirror screen, only one of them should attempt to manage the driver.

    The Mirage driver has a boot-time checker that ensures that the driver is deactivated even when the managing application has failed to deactivate it (for example, when the application has crashed).

The driver is never loaded (and can’t be activated) in the Safe (or VGA) boot mode of Windows.

    Options

    There are some registry-based switches that affect the driver’s behavior.