<?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 id="GUID-DEF3B8B3-5BD7-505B-93F9-A20CE00FFAE6" xml:lang="en"><title>File Server
Plugin Concepts</title><shortdesc>This topic describes the file server plug-in concepts.</shortdesc><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 metadata. 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>
<note> 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></note>
<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">
<image href="GUID-9A4543B3-2A79-5604-AE11-5087507C6755_d0e265930_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 platform 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>Previously,
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>Symbian platform provides plugins
that are 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>Previously,
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_d0e266006_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_d0e266044_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<20> 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<20> 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_d0e266170_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>