DCOM

From Apache OpenOffice Wiki
Jump to: navigation, search



The Automation bridge maps all UNO objects to automation objects. That is, all those objects implement the IDispatch interface. To access a remote interface, the client and server must be able to marshal that interface. The marshaling for IDispatch is already provided by Windows, therefore all objects which originate from the bridge can be used remotely.

To make DCOM work, apply proper security settings for client and server. This can be done by setting the appropriate registry entries or programmatically by calling functions of the security API within the programs. The office does not deal with the security, hence the security settings can only be determined by the registry settings which are not completely set by the office's setup. The AppID key under which the security settings are recorded is not set. This poses no problem because the dcomcnfg.exe configuration tools sets it automatically. [Update] As of OOo 3.2, an AppID entry is written. Using dcomcnfg it will be displayed as "OpenOffice.org Service Manager" or "StarOffice Service Manager".

To access the service manager remotely, the client must have launch and access permission. Those permissions appear as sub-keys of the AppID and have binary values. The values can be edited with dcomcnfg. Also the identity of the service manager must be set to “Interactive User”. When the office is started as a result of a remote activation of the service manager, it runs under the account of the currently logged-on user (the interactive user).

In case of callbacks (office calls into the client), the client must adjust its security settings so that incoming calls from the office are accepted. This happens when listener objects that are implemented as Automation objects (not UNO components) are passed as parameters to UNO objects, which in turn calls on those objects. Callbacks can also originate from the automation bridge, for example, when JScript Array objects are used. Then, the bridge modifies the Array object by its IDispatchEx interface. To get the interface, the bridge has to call QueryInterface with a call back to the client.

To avoid these callbacks, VBArray objects and Value Objects could be used.

To set security properties on a client, use the security API within a client program or make use of dcomcnfg again. The API can be difficult to use. Modifying the registry is the easiest method, simplified by dcomcnfg. This also adds more flexibility, because administrators can easily change the settings without editing source code and rebuilding the client. However, dcomcnfg only works with COM servers and not with ordinary executables. To use dcomcnfg, put the client code into a server that can be registered on the client machine. This not only works with exe servers, but also with in-process servers, namely dlls. Those can have an AppID entry when they are remote, that is, they have the DllSurrogate subkey set. To activate them an additional executable which instantiates the in-process server is required. At the first call on an interface of the server DCOM initializes security by using the values from the registry, but it only works if the executable has not called CoInitializeSecurity beforehand.

To run JScript or VBScript programs, an additional program, a script controller that runs the script is required, for example, the Windows Scripting Host (WSH). The problem with these controllers is that they might impose their own security settings by calling CoInitializeSecurity on their own behalf. In that case, the security settings that were previously set for the controller in the registry are not being used. Also, the controller does not have to be configurable by dcomcnfg, because it might not be a COM server. This is the case with WSH (not WSH remote).

To overcome these restrictions write a script controller that applies the security settings before a scripting engine has been created. This is time consuming and requires some knowledge about the engine, along with good programming skills. The Windows Script Components (WSC) is easier to use. A WSC is made of a file that contains XML, and existing JScript and VBS scripts can be put into the respective XML Element. A wizard generates it for you. The WSC must be registered, which can be done with regsvr32.exe or directly through the context menu in the file explorer. To have an AppID entry, declare the component as remotely accessible. This is done by inserting the remotable attribute into the registration element in the wsc file:

  <registration
      description="writerdemo script component"
      progid="dcomtest.writerdemo.WSC"
      version="1.00"
      classid="{90c5ca1a-5e38-4c6d-9634-b0c740c569ad}"
      remotable="true">

When the WSC is registered, there will be an appropriate AppID key in the registry. Use dcomcnfg to apply the desired security settings on this component. To run the script. An executable is required. For example:

  Option Explicit
  Sub main()
      Dim obj As Object
      Set obj = CreateObject("dcomtest.writerdemo.wsc”)
      obj.run
  End Sub

In this example, the script code is contained in the run function. This is how the wsc file appears:

  <?xml version="1.0"?>
  <component>
  <?component error="true" debug="true"?>
  <registration
      description="writerdemo script component"
      progid="dcomtest.writerdemo.WSC”
      version="1.00"
      classid="{90c5ca1a-5e38-4c6d-9634-b0c740c569ad}"
      remotable="true">
  </registration>
  <public>
      <method name="run">
      </method>
  </public>
  <script language="JScript">
  <![CDATA[
  var description = new jscripttest;
  function jscripttest()
  {
      this.run = run;
  }
  function run()
  {
  var objServiceManager= new ActiveXObject("com.sun.star.ServiceManager”,"\\jl-1036");
  var objCoreReflection= objServiceManager.createInstance("com.sun.star.reflection.CoreReflection");
  var objDesktop= objServiceManager.createInstance("com.sun.star.frame.Desktop");
  var objCoreReflection= objServiceManager.createInstance("com.sun.star.reflection.CoreReflection");
  var args= new Array();
  var objDocument= objDesktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, args);
  var objText= objDocument.getText();
  var objCursor= objText.createTextCursor();
  objText.insertString( objCursor, "The first line in the newly created text document.\n", false);
  objText.insertString( objCursor, "Now we're in the second line", false);
  var objTable= objDocument.createInstance( "com.sun.star.text.TextTable");objTable.initialize( 4, 4);
  objText.insertTextContent( objCursor, objTable, false);
  var objRows= objTable.getRows();
  var objRow= objRows.getByIndex( 0);
  objTable.setPropertyValue( "BackTransparent", false);
  objTable.setPropertyValue( "BackColor", 13421823);
  objRow.setPropertyValue( "BackTransparent", false);
  objRow.setPropertyValue( "BackColor", 6710932);
  insertIntoCell( "A1","FirstColumn", objTable);
  insertIntoCell( "B1","SecondColumn", objTable);
  insertIntoCell( "C1","ThirdColumn", objTable);
  insertIntoCell( "D1","SUM", objTable);
  objTable.getCellByName("A2").setValue( 22.5);
  objTable.getCellByName("B2").setValue( 5615.3);
  objTable.getCellByName("C2").setValue( -2315.7);
  objTable.getCellByName("D2").setFormula("sum <A2:C2>");objTable.getCellByName("A3").setValue( 21.5);
  objTable.getCellByName("B3").setValue( 615.3);
  objTable.getCellByName("C3").setValue( -315.7);
  objTable.getCellByName("D3").setFormula( "sum <A3:C3>");objTable.getCellByName("A4").setValue( 121.5);
  objTable.getCellByName("B4").setValue( -615.3);
  objTable.getCellByName("C4").setValue( 415.7);
  objTable.getCellByName("D4").setFormula( "sum <A4:C4>");
  objCursor.setPropertyValue( "CharColor", 255);
  objCursor.setPropertyValue( "CharShadowed", true);
  objText.insertControlCharacter( objCursor, 0 , false);
  objText.insertString( objCursor, " This is a colored Text - blue with shadow\n",false);
  objText.insertControlCharacter( objCursor, 0, false );
  var objTextFrame= objDocument.createInstance("com.sun.star.text.TextFrame”);
  var objSize= createStruct("com.sun.star.awt.Size");
  objSize.Width= 15000;
  objSize.Height= 400;
  objTextFrame.setSize( objSize);
  objTextFrame.setPropertyValue( "AnchorType", 1);
  objText.insertTextContent( objCursor, objTextFrame, false);
  var objFrameText= objTextFrame.getText();
  var objFrameTextCursor= objFrameText.createTextCursor();
  objFrameText.insertString( objFrameTextCursor, "The first line in the newly created text frame.",false);
  objFrameText.insertString(objFrameTextCursor, "With this second line the height of the frame raises.", false );
  objFrameText.insertControlCharacter( objCursor, 0 , false);
  objCursor.setPropertyValue( "CharColor", 65536);
  objCursor.setPropertyValue( "CharShadowed", false);
  objText.insertString( objCursor, " That's all for now !!", false );
 
  function insertIntoCell( strCellName, strText, objTable)
  {
      var objCellText= objTable.getCellByName( strCellName);
      var objCellCursor= objCellText.createTextCursor();
      objCellCursor.setPropertyValue( "CharColor",16777215);
      objCellText.insertString( objCellCursor, strText, false);
  }
  function createStruct( strTypeName)
  {
      var classSize= objCoreReflection.forName( strTypeName);
      var aStruct= new Array();
      classSize.createObject( aStruct);
      return aStruct[0];
  }
  }
  ]]>
  </script>
  </component>

This WSC contains the WriterDemo example written in JScript.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages