Symbian3/SDK/Source/GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita
author Dominic Pinkman <Dominic.Pinkman@Nokia.com>
Thu, 21 Jan 2010 18:18:20 +0000
changeset 0 89d6a7a84779
permissions -rw-r--r--
Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept xml:lang="en" id="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6"><title>File Server Plugin Concepts</title><prolog><metadata><keywords/></metadata></prolog><conbody><p>File server plugins can issue direct file server requests, interpret and modify inbound messages and change file and meta data. A compression plugin may need to intercept file read or file write requests which are sent from the client to provide a seamless user experience. This operation requires the modification of the data, position and length arguments that are sent from the client to the file server. </p> <p>There are some limitations to the file server plugin framework: </p> <ul><li id="GUID-1C02ECAE-A711-5E2A-8006-EC2D1BF5A859"><p>The file server plugin framework only operates on one client file at any time. However, a plugin itself can operate on any number of files during a single request from the client. </p> </li> <li id="GUID-F82C8E71-479B-5482-8234-C5AD2AD05A91"><p>The file server plugin framework does not enable the compression or encryption of whole volumes. If access to the whole media volume is needed use a <xref href="GUID-983F0ABD-470C-51C3-B6AE-1B1AA55AB4A2.dita">file server extension</xref> rather than a plugin. </p> </li> <li id="GUID-386C0911-30EF-56B0-BD3B-4BC97A7CEFA3"><p>File modification plugins cannot operate on demand paged executables. Demand paging does not use the file server, so the plugin framework cannot be used to encrypt/process the executable. </p> </li> </ul> <p> <b>Note</b>: The improved framework will not prevent deadlock with existing plugins. Plugins that currently issue <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> requests must be migrated to the new APIs to prevent deadlock. Follow the guidelines within the <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita">plugin implementation tutorial</xref>. </p> <ul><li id="GUID-0A5ECCEA-CD70-528D-8880-463CA77D797B"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-8B5B325D-D88C-55A7-9684-C2DCF81FCD79">Plugin type</xref>, </p> </li> <li id="GUID-40202D9E-C136-55BB-A5A1-DF64971B99D1"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-C76B06C8-DEDC-57AC-A510-3DD1E232241A">Architecture</xref>, </p> </li> <li id="GUID-60C8A1F1-6BE6-59A3-8F33-BD7FBFF9FB59"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-6234893D-A1C8-5870-9761-9EA2BD6909F0">Plugin order</xref>, </p> </li> <li id="GUID-20D4D10F-5E92-5FE3-A89C-DAF45E52EB0B"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-DB21C0FD-46F8-5E4F-9288-69AE8609482B">Drive selection</xref>, </p> </li> <li id="GUID-91E1927C-3AA6-5594-8238-EA7B590278B2"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-50F7CD3A-A051-5498-8886-B4501523FD1D">Interception of file server requests</xref>, </p> </li> <li id="GUID-59EB5503-3D02-5E2D-80A4-A20EA8364D81"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-0B7B373D-41ED-5C91-ACC4-393A8669815A">Security</xref>. </p> </li> </ul> <section id="GUID-8B5B325D-D88C-55A7-9684-C2DCF81FCD79"><title>Plugin type</title> <p>There are two different types of file server plugins: </p> <ul><li id="GUID-0FBE9E75-D164-5BCC-B00A-A5A76DBD200C"><p>Observer plugins - intercept requests but do not modify file data or associated meta data. </p> <p>Examples of observer plugins are those for virus scanning or logging. </p> </li> <li id="GUID-69708845-9C79-5C19-B758-AEF8F8A693E0"><p>Modifier plugins - intercept requests and modify the data or associated meta data of the target files or directories.. </p> <p>Examples of file modifier plugins are compression and encryption plugins. </p> </li> </ul> </section> <section id="GUID-C76B06C8-DEDC-57AC-A510-3DD1E232241A"><title>Architecture</title> <p>This section describes the structure of the plugin framework and the changes that have been made to the framework in v9.5: </p> <ul><li id="GUID-399FE2E3-6576-5F98-83A8-70B9F77C65B7"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-3D91570E-8939-557B-8E1E-3A3C5BD27A26">Threads and execution context</xref>, </p> </li> <li id="GUID-609612CB-E684-5BDA-88FC-16FFB71D70C2"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-71DC7464-0EF0-5F78-816E-24F73F5FCA12">Exclusive access</xref>, </p> </li> <li id="GUID-665C36D1-DDD3-5DA4-86A3-574DFDC38AFF"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-9C152BE3-9113-5A0C-8EE2-81ADD09BEAD2">Intercepting requests to the ROM drive</xref>, </p> </li> <li id="GUID-F06D0F56-40AA-5631-9686-BA955E8E263B"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-AA3990F3-52AB-5B14-8ED4-50CCA824AF84">Preventing deadlock</xref>. </p> </li> </ul> <p>The diagram below shows how plugins fit into the File Server software stack. </p> <fig id="GUID-EF5AECEC-9CB0-54B0-B6D2-46266B5FF49E"><title>
             File Server Stack
          </title> <image href="GUID-9A4543B3-2A79-5604-AE11-5087507C6755_d0e237755_href.png" placement="inline"/></fig> <p> <b>Note</b>: More than one plugin can be loaded into the file server at the same time. A plugin is not aware of other plugins. </p> <p id="GUID-3D91570E-8939-557B-8E1E-3A3C5BD27A26"><b> Threads and execution context</b> </p> <p>The Symbian OS File Server has multiple threads. There is a thread for each drive in use and a main thread that receives the requests from clients and sends them to the drive threads. Synchronous drives, however, do not have their own drive thread; requests for these are processed by the main thread. There is also a separate thread for processing session disconnect requests. </p> <p>Each plugin also has its own thread for processing requests. Requests are dispatched to the plugin thread associated with the request's drive before they are dispatched to the drive thread. This is discussed in more detail in <xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-50F7CD3A-A051-5498-8886-B4501523FD1D">interception of file server requests</xref>. </p> <p id="GUID-71DC7464-0EF0-5F78-816E-24F73F5FCA12"><b>Exclusive access</b> </p> <p>Prior to Symbian OS v9.5, when a client application opens a file for exclusive write access, no other clients could access the file until the client closed its associated subsession. This also applied to plugins that needed to modify file data (as they are also clients of the file server). </p> <p>In Symbian OS 9.5+ plugins are now able to perform operations on files and directories irrespective of the mode in which the file has been opened. </p> <p>Operations are now able to use the same file handle as the originating request (run in the same context as the original request) so files opened for exclusive access can still be written to by a plugin wishing to modify the file. </p> <p id="GUID-9C152BE3-9113-5A0C-8EE2-81ADD09BEAD2"><b>Intercepting ROM drive requests</b> </p> <p>Prior to Symbian OS v9.5, plugins could not intercept any requests to the ROM drive (Z) however, there is a requirement to be able to intercept requests on this drive to enable secure-load and logging plugins. Requests to drive Z can now be intercepted by plugins. See the tutorial for <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-89CF85BE-784F-5237-9F78-69D603B650C4">CFsPluginFactory</xref> for more details. </p> <p id="GUID-AA3990F3-52AB-5B14-8ED4-50CCA824AF84"><b>Preventing deadlock</b> </p> <p>The new framework allows a plugin to have direct access to file data without the need to issue new file server requests through the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref>, <xref href="GUID-12AE154F-7741-38C0-ADFE-9784FCF5E516.dita"><apiname>RDir</apiname></xref> and <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> client APIs. In the pre-9.5 approach it was possible to reach deadlock if more than one plugin was present. </p> <p>The diagram below shows two plugins in the pre v9.5 framework. If both plugins issue new file server requests and if the plugins are not re-entrant safe this can lead to deadlock in the file server. </p> <fig id="GUID-01A69E82-BF01-520A-A8C5-927F1ED85E04"><title>
                File server deadlock 
             </title> <image href="GUID-9CC5E096-74FB-59AB-BAB9-A5486B961B7D_d0e237829_href.png" placement="inline"/></fig> <p>The framework introduced in v9.5 prevents deadlock by allowing plugins to issue internal file server requests after intercepting a request by using the newly introduced <xref href="GUID-3C50CF63-9AF4-3F36-8B8F-3FBB613E1CAC.dita"><apiname>RFilePlugin</apiname></xref>, <xref href="GUID-2E871434-D08F-3275-AC55-260A9A78661A.dita"><apiname>RDirPlugin</apiname></xref> and <xref href="GUID-DE8D8017-6E9C-38CE-A023-98A53CDF7152.dita"><apiname>RFsPlugin</apiname></xref> APIs and not by using the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref>, <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> and <xref href="GUID-12AE154F-7741-38C0-ADFE-9784FCF5E516.dita"><apiname>RDir</apiname></xref> APIs. Internally issued requests are only dispatched to plugins mounted below the issuing plugin and the appropriate drive thread. </p> <p>The sequence of events for a typical plugin intercepting a file read request is illustrated below: </p> <fig id="GUID-E366027F-3112-520F-A118-4C048102749E"><title>
                Read request intercepted by a plugin 
             </title> <image href="GUID-2ABCF233-7DCC-59E2-B075-81E148A1D2AB_d0e237865_href.png" placement="inline"/></fig> <p>The classes <xref href="GUID-3C50CF63-9AF4-3F36-8B8F-3FBB613E1CAC.dita"><apiname>RFilePlugin</apiname></xref>, <xref href="GUID-2E871434-D08F-3275-AC55-260A9A78661A.dita"><apiname>RDirPlugin</apiname></xref> and <xref href="GUID-DE8D8017-6E9C-38CE-A023-98A53CDF7152.dita"><apiname>RFsPlugin</apiname></xref> have been introduced to facilitate plugins with direct access behaviour on file and directory requests. These classes are analogous to the client-side <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref>, <xref href="GUID-12AE154F-7741-38C0-ADFE-9784FCF5E516.dita"><apiname>RDir</apiname></xref> and <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> classes and have functions with similar or identical signitures. </p> <p>In order to perform requests on a file it is necessary to open a sub-session by calling either <xref href="GUID-EC8FDB25-3DD7-3F1C-9875-0FA9315AE9AC.dita"><apiname>AdoptFromClient()</apiname></xref> or <xref href="GUID-20D0D10F-3401-3F72-8AF6-DC35F6025DC2.dita"><apiname>Open()</apiname></xref>. <codeph>AdoptFromClient()</codeph> is used in order to open a sub-session with the file associated with the client’s request. Alternatively the <codeph>Open()</codeph> method can be used to open either a different file, or the file associated with the client’s request possibly with a different access mode. </p> <p>More than one file can be opened at any time by creating multiple instances of <xref href="GUID-3C50CF63-9AF4-3F36-8B8F-3FBB613E1CAC.dita"><apiname>RFilePlugin</apiname></xref>. </p> <p>The following example shows how to open many files from a plugin during a single request: </p> <codeblock id="GUID-AFCA6392-2414-591A-98C5-A9FC2C103755" xml:space="preserve">// Define the object
RFilePlugin clientsFile(aRequest); 

// Opens the file associated with the intercepted request
Tint r = clientsFile.AdoptFromClient();
User::LeaveIfError(r);
TBuf&lt;20&gt; data;
TInt64 pos = (Tint64)0;
Tint length = 0;

// Read the file
r = clientsFile.Read(pos, data, length);
User::LeaveIfError(r);

// Open a second file
RFilePlugin secondFile(aRequest);
_LIT(KSecondName, ”D:\\myfile.txt”);
r = secondFile.Open(KSecondName(), EFileRead);
User::LeaveIfError(r);

// Read from second file
TBuf&lt;20&gt; data2;
TInt64 pos2 = (Tint64)0;
Tint length2 = 0;

// Read the file
r = secondFile.Read(pos2, data2, length2);
User::LeaveIfError(r);

// Close the files
clientsFile.Close();
secondFile.Close();</codeblock> <p><b>Issuing an internal file system request</b> </p> <p>An internal request can be marked as ‘Direct to Drive’. This allows requests that are generated by a plugin to be dispatched straight to the drive thread bypassing all other plugins which may be mounted below the plugin that issued the request. After being processed by the drive thread the request also bypasses the plugins between the drive thread and the plugin that the Direct to Drive request originated from. Once returned to the plugin that generated the request, the Direct to Drive request is complete and any other requests issued from the plugin are processed by plugins further down the plugin-stack in the normal manner. </p> <p>The last argument of the <xref href="GUID-3C50CF63-9AF4-3F36-8B8F-3FBB613E1CAC.dita"><apiname>RFilePlugin</apiname></xref> constructor of the classes <xref href="GUID-3C50CF63-9AF4-3F36-8B8F-3FBB613E1CAC.dita"><apiname>RFilePlugin</apiname></xref>, <xref href="GUID-DE8D8017-6E9C-38CE-A023-98A53CDF7152.dita"><apiname>RFsPlugin</apiname></xref> and <xref href="GUID-2E871434-D08F-3275-AC55-260A9A78661A.dita"><apiname>RDirPlugin</apiname></xref> is named <codeph>aDirectToDrive</codeph>. <codeph>aDirectToDrive</codeph> is a boolean value (<codeph>TBool</codeph>) to indicate that the request is Direct to Drive. The default value is <codeph>EFalse</codeph> indicating that the request is interceptable by plugins further down the plugin-stack. </p> </section> <section id="GUID-6234893D-A1C8-5870-9761-9EA2BD6909F0"><title>Plugin order</title> <p>The Plugin framework provides support for multiple plugins to be present and active. Plugins are arranged in a stack. Plugins intercept requests in the order they are arranged in the stack with the plugin at the top of the stack (at the smallest numerical absolute position) getting the first intercept. The order of plugins in the stack is therefore crucial to the correct operation of the file server when more than one plugin is active, especially when the plugins are modifier plugins (i.e when both modify the data or parameters of the requests). </p> <p>If two plugins are active and one of those is a virus scanner, for the virus scanner to operate correctly it must be the first plugin to intercept requests. This is so that the virus scanner can have first refusal to block any requests for files which it believes may not be safe for opening. If there is another plugin higher in the stack then this plugin could send Direct To Drive requests, for example, and would significantly reduce the virus scanning ability of the virus scanning plugin. </p> <p>Two mechanisms are provided that allow plugin authors to control the position of their plugins in the plugin stack these are Absolute position and Unique position. </p> <p id="GUID-5C258D67-C324-5FA4-894A-88532F925EFF"><b>Absolute position </b> </p> <p>Plugins can be inserted into the stack by specifying an absolute position at mount time. This absolute position is the index in the internal array of plugins in which the plugin should be mounted. The plugin at position 0 being the first plugin to be able to intercept requests. </p> <fig id="GUID-41EB2F58-407F-52C7-A40C-0E3858CF718B"><title>
                Plugin stack showing absolute positions 
             </title> <image href="GUID-64BDD1DA-6B93-5F45-8CBD-7DBAF92CC4C7_d0e237989_href.png" placement="inline"/></fig> <p>The absolute position method is more appropriate for mounting plugins that operate regardless of their position in the plugin stack or when all of the plugins for a device are known and installed when manufactured. This method does not suit plugins that are added after manufacture where the dependencies of other available plugins is not known. If this is the case use the unique position method described below. </p> <p id="GUID-90FC1AD9-D709-5105-A445-0AA3D7BA85B7"><b>Unique position</b> </p> <p>Plugins can be ordered according to a unique position stored within the plugin. Unique position identifiers are defined by the manufacturer during the software validation/signing process. Unique positions are defined in the derived <xref href="GUID-8A3B2A79-05A6-3BD7-AEA9-02435476F45E.dita"><apiname>CFsPluginFactory</apiname></xref> class. See the description in <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-89CF85BE-784F-5237-9F78-69D603B650C4">CFsPluginFactory</xref>. </p> <p>The position value specifies the category and position of the plugin: </p> <table id="GUID-22362455-13BE-5A26-8750-A94E79941EF3"><tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/><tbody><row><entry><p> <b>plugin Type</b>  </p> </entry> <entry><p> <b>Unique Position Range</b>  </p> </entry> </row> <row><entry><p>File Observers </p> </entry> <entry><p> <codeph>0x20000000 - 0x2FFFFFFF</codeph>  </p> </entry> </row> <row><entry><p>File Modifiers </p> </entry> <entry><p> <codeph>0x40000000 - 0x4FFFFFFF</codeph>  </p> </entry> </row> </tbody> </tgroup> </table> <p>File Observers do not modify data so they are allocated a lower range of numbers placing them at the top of the plugin stack. File Modifiers modify the data stream so they are allocated a higher range placing them lower down the plugin stack. </p> <p> <b>Note</b>: a plugin has a unique position then do not specify an <xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-5C258D67-C324-5FA4-894A-88532F925EFF">absolute position</xref> when mounting it, otherwise the error <codeph>KErrNotSupported</codeph> is returned. </p> </section> <section id="GUID-DB21C0FD-46F8-5E4F-9288-69AE8609482B"><title>Drive selection</title> <p>A File Server Plugin can intercept requests for a specific drive or for all drives. A plugin that intercepts requests for all drives must filter requests that are not appropriate for some drives. Requests can be filtered within an overridden <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-97427151-C6E4-5FE4-8197-0D7C58EDB29F">CFsPlugin::Deliver()</xref> function. </p> <p>There are two ways to specify a drive: </p> <ul><li id="GUID-296E3A2E-5985-5E4B-96A2-D247D1FAA07C"><p>When the plugin is mounted. See <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-BED54BD9-2F3F-588E-854B-C28745C8F30A">mounting a plugin</xref>. </p> </li> <li id="GUID-080CD9C3-2BEA-5209-974A-910606EBF22A"><p>At run-time through the use of <xref href="GUID-8A3B2A79-05A6-3BD7-AEA9-02435476F45E.dita#GUID-8A3B2A79-05A6-3BD7-AEA9-02435476F45E/GUID-45A67073-5EF4-3966-A2FD-555B56C89284"><apiname>CFsPluginFactory::iSupportedDrives</apiname></xref>. See the tutorial for <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-89CF85BE-784F-5237-9F78-69D603B650C4">CFsPluginFactory</xref>. </p> </li> </ul> <p>If the drive is not specified then <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita#GUID-E263C747-946F-35AA-9F1D-41833BD350FC/GUID-61640192-646E-33DA-B186-5EE63B07A998"><apiname>RFs::MountPlugin()</apiname></xref> attempts to mount the plugin for all drives. If this behaviour is not supported by the plugin <xref href="GUID-F89DA3F0-2A48-3F9B-8F08-29350E92D0E4.dita"><apiname>KErrNotSupported</apiname></xref> is returned. </p> </section> <section id="GUID-50F7CD3A-A051-5498-8886-B4501523FD1D"><title> Interception of file server requests</title> <p>After a file server request has been initialised by the main file server thread it can be intercepted by a plugin. There are two types of intercept: </p> <ul><li id="GUID-288866F8-ABE5-5569-A70C-2C86B4F073B9"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-05F613B8-FF66-54B6-8D49-2BF92914E54E">pre-operation intercepts</xref>, </p> </li> <li id="GUID-E876E576-1E94-5F06-8305-22D620A82B6F"><p><xref href="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6.dita#GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6/GUID-59FD1CED-5A32-5F6E-A256-821A2783D065">post-operation intercepts</xref>. </p> </li> </ul> <p>Plugins can register for pre-intercepts, for post-intercepts or for both pre and post-intercepts. </p> <p id="GUID-05F613B8-FF66-54B6-8D49-2BF92914E54E"><b>Pre-operation</b> </p> <p>Pre-operation intercepts occur before the drive associated with a request processes it. In a file write request for example, the pre-intercept operations occur before data has been written to the file. Requests are passed down the plugin-stack from the file server towards the drive thread. </p> <p>When the main file server thread has initialised a request, the request is dispatched to the highest plugin in the stack. This plugin must have been mounted on the requested drive and registered to pre-intercept this type of request. See <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-BED54BD9-2F3F-588E-854B-C28745C8F30A">mounting a plugin</xref>. The request is dispatched by calling the plugin's <xref href="GUID-BC0DB991-EF52-3344-8E6A-F8060B75A189.dita#GUID-BC0DB991-EF52-3344-8E6A-F8060B75A189/GUID-2EACA8A8-D569-3D6A-9383-451587A65839"><apiname>CFsPlugin::Deliver()</apiname></xref> function. </p> <p>The <codeph>Deliver()</codeph> function runs in the context of the previous calling thread, this can be the main file server thread or a plugin thread. Override <codeph>CFsPlugin::Deliver()</codeph> to filter the request. If the <codeph>Deliver()</codeph> function has not been overridden then the request is dispatched for asynchronous processing by calling the base class <codeph>Deliver()</codeph>. See the <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-97427151-C6E4-5FE4-8197-0D7C58EDB29F">CFsPlugin::Deliver()</xref> tutorial section. </p> <p id="GUID-59FD1CED-5A32-5F6E-A256-821A2783D065"><b>Post operation</b> </p> <p>Post-operation intercepts occur after the drive associated with a request has processed it. In a file write request for example, the post-intercept occurs after data has been written to the file. Requests are passed from the drive thread back up the stack towards the client. </p> <p>When the drive thread has finished processing a request it dispatches it to the plugin lowest in the stack by calling the plugin's <xref href="GUID-C6F20230-3D6C-3392-B040-CF627534B930.dita"><apiname>Deliver()</apiname></xref> function. </p> <p><b> Filtering requests internally</b> </p> <p>The <xref href="GUID-F1B37142-1EEF-3777-82B1-303982B888EC.dita#GUID-F1B37142-1EEF-3777-82B1-303982B888EC/GUID-8EBEAD17-B03C-3DBA-9A47-0F7DB07785F9"><apiname>CFSPlugin::Deliver()</apiname></xref> function filters the request and decides what kind of action is neccessary in terms of the flow of the request through the plugin stack: </p> <ul><li id="GUID-3E8CAD7B-BE13-531E-A387-432F4CD463C9"><p> <xref href="GUID-1E025D93-3D66-3E88-830D-CBB3A471A777.dita"><apiname>KPluginMessageForward</apiname></xref> is returned if the intercept is pre-operation. The request is passed to the next plugin down the stack or to the drive thread if there are no more plugins. </p> </li> <li id="GUID-1FFEFFF4-3D5F-590F-8884-CA27B2B5B916"><p> <xref href="GUID-81C5F6A1-3FCA-33E5-99C6-7901D41BCBDE.dita"><apiname>KPluginMessageComplete</apiname></xref> is returned if the intercept is post-operation. The request is passed to the next plugin up the stack or if there are no more plugins to process the request it is passed to the main file server thread. </p> </li> </ul> <p>If the request requires processing by the plugin then the plugin's <codeph>Deliver()</codeph> function calls the base class <codeph>Deliver()</codeph> function and the request is dispatched to the plugin's thread for asynchronous processing. </p> <p>Asynchronous processing is carried out in the plugin's <xref href="GUID-8EF10689-68B7-391B-AD5C-4F51780165FF.dita"><apiname>DoRequestL()</apiname></xref> function. A plugin can only have a single <codeph>DoRequestL()</codeph> function which must handle both pre and post-intercepts. Plugin authors can use the <xref href="GUID-06E787C2-FAC1-36D2-9C64-11BDA1B656F1.dita"><apiname>IsPostOperation()</apiname></xref> function of the utility class, <xref href="GUID-A814151C-8AEC-3E16-8691-33174B64E36F.dita"><apiname>TFsPluginRequest</apiname></xref> to indicate whether the <codeph>DoRequestL()</codeph> is processing a request as a pre-intercept or post-intercept. See the description of <xref href="GUID-00764271-AD6B-5F41-AF72-843107EBF95F.dita#GUID-00764271-AD6B-5F41-AF72-843107EBF95F/GUID-14773530-7C15-52E2-A542-72A0B2163461">TFsPluginRequest</xref>. </p> <p>Once the asynchronous processing is complete the <codeph>DoRequestL()</codeph> function returns <codeph>KErrNone</codeph> and the request is passed to the next plugin down the stack by calling its <xref href="GUID-C6F20230-3D6C-3392-B040-CF627534B930.dita"><apiname>Deliver()</apiname></xref> function. If there are no lower plugins then the request is passed to the appropriate drive thread for processing. </p> <p>If the plugin intercepts a request in pre-operation and wants to complete the request on behalf of the client then the plugin can return <xref href="GUID-DCECEF73-9C33-3C14-951D-E75D89B21FBA.dita"><apiname>KErrCompletion</apiname></xref> to indicate that the request has been completed and that the request is now in post operation mode. The flow will then proceed to any previous plugins if mounted or directly back to the client otherwise. <xref href="GUID-DCECEF73-9C33-3C14-951D-E75D89B21FBA.dita"><apiname>KErrCompletion</apiname></xref> prevents any further plugins further down the stack from intercepting the request. </p> <p>When a plugin intercepts file read or file write and does an early completion (i.e. returns <xref href="GUID-DCECEF73-9C33-3C14-951D-E75D89B21FBA.dita"><apiname>KErrCompletion</apiname></xref> in pre-intercept) then the plugin author should call <xref href="GUID-A814151C-8AEC-3E16-8691-33174B64E36F.dita#GUID-A814151C-8AEC-3E16-8691-33174B64E36F/GUID-149E1448-63AA-3F08-A3A2-606D240A8927"><apiname>TFsPluginRequest::SetSharePos()</apiname></xref> to allow share position to be updated after early read/write completion. </p> </section> <section id="GUID-0B7B373D-41ED-5C91-ACC4-393A8669815A"><title>Security</title> <p>File server plugins are implemented as libraries that are loaded into the file server process at runtime. Therefore, plugins must have the same <xref href="GUID-4BFEDD79-9502-526A-BA7B-97550A6F0601.dita">platform security</xref> capabilities as the file server process, these are <xref href="GUID-2A022229-C333-3B0A-99A5-13CA0710025D.dita"><apiname>TCB</apiname></xref>, <xref href="GUID-E5C21B79-529B-397E-8A22-63612CA52869.dita"><apiname>ProtServ</apiname></xref>, <xref href="GUID-8DC76E7B-9EB3-3848-AD8D-3D519388A504.dita"><apiname>DiskAdmin</apiname></xref>, <xref href="GUID-ECCA7246-B2BA-3261-95C9-9E72C6EC51D4.dita"><apiname>AllFiles</apiname></xref>, <xref href="GUID-93881606-AA56-385F-A958-3957142BEFE3.dita"><apiname>PowerMgmt</apiname></xref> and <xref href="GUID-616F0C5B-D2C1-39D8-9BFC-53A2AEC7C850.dita"><apiname>CommDD</apiname></xref>. </p> <p>Any user side process that wishes to load and mount plugins must have the <codeph>DiskAdmin</codeph> capability. </p> </section> </conbody></concept>