--- a/Symbian3/PDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita Tue Jul 20 12:00:49 2010 +0100
+++ b/Symbian3/PDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita Fri Aug 13 16:47:46 2010 +0100
@@ -1,347 +1,347 @@
-<?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-E93D3767-0F74-5335-8233-8236908F70AF" xml:lang="en"><title>How
-to share file handles between processes</title><shortdesc>This section describes the sharing of file handles between two
-processes, and the APIs provided for this purpose. This feature is only supported
-on Symbian platform versions with EKA2 architecture. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
-<p>It is possible to share file handles between two processes, allowing an
-open file to be passed from one process to another. This is a necessary feature
-in secure versions of Symbian platform. </p>
-<p>Some further implementation considerations are provided to support this
-mechanism. A description of passing file handles is given, followed by examples,
-which show you how to implement a binary using this feature. </p>
-<p> <b>See also</b> </p>
-<p> <xref href="GUID-B69FE02E-3A78-5438-BA7C-F7BB4CD3EB76.dita">File Server Client
-Side Overview</xref> </p>
-<p> <xref href="GUID-4BFEDD79-9502-526A-BA7B-97550A6F0601.dita">Platform security</xref>. </p>
-<p>This section contains the following topics: </p>
-<ul>
-<li id="GUID-79142E0A-C7F1-5545-A152-62C2EF681CC0"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-E5383F93-C846-5A10-BD59-6FE4754FDCD9">Overview</xref> </p> </li>
-<li id="GUID-0CFEA4B0-C2EF-58A0-BE24-A55E695ED6FD"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-16841C97-292A-5EF3-BE88-EE35BF3A0BC8">APIs that support the sharing of file handles</xref> </p> </li>
-<li id="GUID-1B37219E-0980-5B45-8C38-76CD59A8240D"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF">Example 1 - Client passing a file handle to a server</xref> </p> </li>
-<li id="GUID-DFCCFD0E-083E-50CD-9029-AE663311AFC4"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-707872E2-CD5D-5883-A3F5-C66B34C26035">Example 2 - Client requesting a file handle from a server</xref> </p> </li>
-<li id="GUID-A0A1C7DC-177F-5D13-8E89-5952A68D07A2"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-8457BB92-54A3-578B-99AA-0AD5EF8C3068">Example 3 - Client passing a file handle to another process</xref> </p> </li>
-<li id="GUID-167D7C88-4802-57F7-9331-EB6228EC7DDC"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-DB2E90FD-5847-54EA-AA40-B7C298AC7801">Implementation Considerations</xref> </p> </li>
-<li id="GUID-987CE666-F693-5459-9157-AE9CB9DEC9CC"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-E94C9F16-0F5B-5DCB-B644-A022D26A029C">Testing</xref> </p> </li>
-<li id="GUID-B5815E9B-EA0A-5B49-95EF-C010B5D29FFA"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-061BD238-43D0-5099-95B0-7E811CA59DAF">Summary</xref>. </p> </li>
-</ul>
-<section id="GUID-E5383F93-C846-5A10-BD59-6FE4754FDCD9"><title>Overview</title> <p>Allowing
-an open file to be passed from one process to another is a necessary feature
-in secure versions of Symbian platform. The platform security model provides
-a <i>data caging</i> mechanism, allowing processes and the OS itself to hide
-private data from other processes. </p> <p>However, while it is desirable
-to keep a file safe from other processes, it is useful to give a specific
-process access to the file: </p> <ul>
-<li id="GUID-2553DE33-4C67-5258-862E-00B04CA17EB5"><p>without the need to
-give that process any special capabilities </p> </li>
-<li id="GUID-CB0364D9-2975-5829-ADFF-AD178BF8192C"><p>without the need to
-give the recipient of the file the full path name of that file. </p> </li>
-</ul> <p>New <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> member functions enable an open file
-handle to be passed from client to a server, from server to a client or from
-one process to another process. </p> <p>Note that file handles are not really
-handles in the usual sense of referring to a kernel object, but are simply
-numbers that refer to an open file within a file server session. </p> </section>
-<section id="GUID-16841C97-292A-5EF3-BE88-EE35BF3A0BC8"><title>APIs that support
-the sharing of file handles</title> <p>The following <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> member
-functions support the sharing of file handles between processes: </p> <ul>
-<li id="GUID-C76BE924-7A28-5983-A9D4-05CCECF1B413"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-570BA348-E033-3A63-B702-D2554E95BF0B"><apiname>RFile::AdoptFromClient()</apiname></xref> </p> </li>
-<li id="GUID-EE3FEBF4-6736-5B20-BD9E-21C752239B80"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-2E66E1ED-01FF-3610-BDB7-E83FE1559934"><apiname>RFile::AdoptFromServer()</apiname></xref> </p> </li>
-<li id="GUID-21A5C873-A1F9-595F-92CE-0FE5F27939AE"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-943F64CA-B987-3BF5-B22F-5C637F12EEF4"><apiname>RFile::AdoptFromCreator()</apiname></xref> </p> </li>
-<li id="GUID-972A6339-060D-59E0-94E1-4293A85ED5B2"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-3633606B-09E6-3DD7-8FA3-E20A16CFB87F"><apiname>RFile::TransferToServer()</apiname></xref> </p> </li>
-<li id="GUID-5FF4033F-68F0-5024-8E38-BFF7846661A1"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-B25BF021-8298-397E-9C3B-E4D2E591D88F"><apiname>RFile::TransferToClient()</apiname></xref> </p> </li>
-<li id="GUID-ECC89636-84B4-5B0B-8E31-6BE721D09405"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-FBE294F0-28C3-30E5-A6E4-E82699607216"><apiname>RFile::TransferToProcess()</apiname></xref> </p> </li>
-<li id="GUID-ADA3EBCC-25AB-5E3D-B380-0D3BF643578E"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-EF48ADCC-01F7-3680-B090-9856301E3B9D"><apiname>RFile::Name()</apiname></xref> </p> </li>
-<li id="GUID-63B6C3C7-902A-540F-B8DA-ECE10AB8EE5C"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-88AC4973-622F-350D-9957-8FA5D409B129"><apiname>RFile::Duplicate()</apiname></xref> </p> </li>
-</ul> <p>The owner of an open <xref href="GUID-D3B4DF9D-BC59-36C1-BE81-D5B5591B2C63.dita"><apiname>Rfile</apiname></xref> object uses the <codeph>Transfer***()</codeph> member
-functions to transfer ownership of that object to another process. Note that
-the file-server session must be marked as shareable by calling <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita#GUID-E263C747-946F-35AA-9F1D-41833BD350FC/GUID-7FD79082-9F32-376B-9BFB-914CA704E3FF"><apiname>RFs::ShareProtected()</apiname></xref> before
-any file handles are transferred, otherwise the <codeph>Transfer***()</codeph> functions
-return <xref href="GUID-25493BDC-2D2E-3CC5-A5FE-A36804A4388A.dita"><apiname>KErrBadHandle</apiname></xref>. </p> <p>A receiving process uses
-the <codeph>Adopt***()</codeph> member functions to adopt an <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object
-passed from another process. </p> <p>A receiving process uses the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-EF48ADCC-01F7-3680-B090-9856301E3B9D"><apiname>RFile::Name()</apiname></xref> member
-function to retrieve the file name and extension (but not the path) from the
-adopted <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object. This is needed mainly by recognisers,
-which sometimes examine a file’s extension to determine whether it is valid
-or not. </p> <p>The <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-88AC4973-622F-350D-9957-8FA5D409B129"><apiname>RFile::Duplicate()</apiname></xref> member function
-allows a process to clone a received <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object so that,
-for example, two separate functions or threads in the receiving process can
-read the file independently. </p> <p>As another example, consider a client
-that only grants access to its <i>data caged</i> private area files, to a
-specific system server. The process that opens the file and shares it (using
-one of the <codeph>Transfer***()</codeph> functions) controls read and write
-access to the file, while the corresponding client or server simply calls
-one of the <codeph>Adopt***()</codeph> functions. In effect, the <codeph>Adopt***()</codeph> functions
-behave like a file opening API such as <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-D5DCA731-EEC7-395A-91EC-2848DFBF5EF8"><apiname>RFile::temp()</apiname></xref>, <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-1EB4AA8F-9363-3EC5-8AE2-1F70F15FCF15"><apiname>RFile::Create()</apiname></xref> and <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-72470A68-7E07-30EF-A3C8-AA855CDAF60E"><apiname>RFile::Open()</apiname></xref>.
-The adopted file retains the access attributes of the file set by the process
-doing the sharing. The access attributes of the file can be changed by the
-adopting process if the security model permits it. </p> <p>The following sections
-present example code and describe how to share a file between two processes.
-This example code uses a simple server that offers the kind of APIs required
-to implement the sharing. Details of this server are not given. </p> <p>Note
-that for the sake of clarity, there is no error checking in the example code. </p> </section>
-<section id="GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF"><title>Example 1 -
-Client passing a file handle to a server</title> <p>In this example, a client
-passes an open file’s handle to a server. The server in turn passes the handle
-over to a second server. </p> <p>The example assumes that the paths and files
-used exist and are correct. A file server session (it is recommended that
-this session is used specifically for this purpose) is set as <i>shared</i> by
-calling <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita#GUID-E263C747-946F-35AA-9F1D-41833BD350FC/GUID-7FD79082-9F32-376B-9BFB-914CA704E3FF"><apiname>RFs::ShareProtected()</apiname></xref>. This enables the session
-to be used by another process. The file is then opened (it exists in the client’s
-private directory). The subsession handle and the fileserver session are then
-passed to the server using <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-3633606B-09E6-3DD7-8FA3-E20A16CFB87F"><apiname>RFile::TransferToServer()</apiname></xref>. The
-file handle can now be adopted by the server’s process. </p> <p><b>Client code: </b> </p> <codeblock id="GUID-D31EA6BD-53F3-5DF8-A447-96C1E99564AE" xml:space="preserve">
-
- RFileHandleSharer handsvr; // handle to server1
- User::LeaveIfError(handsvr.Connect()); // connect to server1
- CleanupClosePushL(handsvr);
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
- User::LeaveIfError(fs.ShareProtected());
-
- RFile file;
- User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
- CleanupClosePushL(file);
-
-
- // store the RFs handle in message slot 0 and the RFile handle in slot 1
- TIpcArgs ipcArgs;
- User::LeaveIfError(file.TransferToServer(ipcArgs, 0, 1));
-
- // send to server
- User::LeaveIfError(handsvr.SendReceive(EMsgXXX, ipcArgs));
-
- // ...continue to use file
- //
-
- CleanupStack::PopAndDestroy(3); // close file, fs, and handsvr
-</codeblock> <p><b>Server1 code: </b> </p> <codeblock id="GUID-73CA766C-FE29-56C1-94C3-2FC23CAC910E" xml:space="preserve">
-
- void CFHSession::PassFileHandleL(const RMessage2& aMsg)
- {
- RFileHandleSharer2 handsvr2; // connect to server2
- User::LeaveIfError(handsvr2.Connect());
- CleanupClosePushL(handsvr2);
-
- RFile file;
-
- // Adopt the file using the RFs handle from message slot 0 and the RFile handle from slot 1
- User::LeaveIfError(file.AdoptFromClient(aMsg, 0, 1));
- CleanupClosePushL(file);
-
- // Use the file
- // …
-
-
- // pass the file handle on to server2
- TIpcArgs ipcArgs;
- User::LeaveIfError(file.TransferToServer(ipcArgs, 0, 1));
- User::LeaveIfError(handsvr2.SendReceive(EMsgXXX, ipcArgs));
-
- // continue to use file
- // …
-
- CleanupStack::PopAndDestroy(2); // close file and handsvr2
-
- aMsg.Complete(KErrNone);
- }
-
-</codeblock> <p><b>Server2 code: </b> </p> <codeblock id="GUID-A48D53BF-9616-5CBD-91FD-588D1EED71F7" xml:space="preserve">
-
- void CFHSession2::PassFileHandleL(const RMessage2& aMsg)
- {
- RFile file;
-
- // Adopt the file using the RFs handle from message slot 0 and the RFile handle from slot 1
- User::LeaveIfError(file.AdoptFromClient(aMsg, 0, 1));
- CleanupClosePushL(file);
-
- // ..use the file
-
- CleanupStack::PopAndDestroy(); // close file
-
- aMsg.Complete(KErrNone);
- }
-
-</codeblock> </section>
-<section id="GUID-707872E2-CD5D-5883-A3F5-C66B34C26035"><title>Example 2 -
-Client requesting a file handle from a server</title> <p>This example is similar
-to <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF">Example
-1</xref> but there are some differences. </p> <p>A client connects to a server
-that provides a shared fileserver session and a file handle to an open file
-when requested. </p> <p><b>Client code: </b> </p> <codeblock id="GUID-D93672C4-9FBA-543F-8C2B-5F7ABFCC2A50" xml:space="preserve">
-
- RFileHandleSharer handsvr; // handle to server
- User::LeaveIfError(handsvr.Connect()); // connect to server
- CleanupClosePushL(handsvr);
-
- // Retrieve the RFs and RFile handles from the server
- TInt fsh; // session (RFs) handle
- TPckgBuf<TInt> fh; // sub-session (RFile) handle
-
- fsh = handsvr.SendReceive(EMsgXXX, TIpcArgs(&fh)); // pointer to fh in slot 0
- User::LeaveIfError(fsh);
-
-// Adopt the file using the returned handles
-RFile file;
-User::LeaveIfError(file.AdoptFromServer(fsh, fh()));
- CleanupClosePushL(file);
-
-// ..use the file
-//
-
- CleanupStack::PopAndDestroy(2); // close file and handsvr
-
-</codeblock> <p><b>Server code: </b> </p> <codeblock id="GUID-4A16D8FB-C235-5DE6-A8E3-A7042DDCBBD4" xml:space="preserve">
-
- void CFHSession::GetFileHandleL(const RMessage2& aMsg)
- {
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- User::LeaveIfError(fs.ShareProtected());
-
- RFile file;
- User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
-
- // transfer to client: store the RFile handle into the package buffer in slot 0
- // and complete the message with the RFs handle
- // NB this assumes that if TransferToClient() return an error, then
- // the standard CServer2::RunError() will complete the message
- User::LeaveIfError(file.TransferToClient(aMsg, 0));
- ASSERT(aMsg.IsNull()); // message should have been completed
-
- file.Close();
- CleanupStack::PopAndDestroy(1); // fs
- }
-
-</codeblock> </section>
-<section id="GUID-8457BB92-54A3-578B-99AA-0AD5EF8C3068"><title>Example 3 -
-Client passing a file handle to another process</title> <p><b>Creator code: </b> </p> <codeblock id="GUID-92F72808-9A52-5504-8580-EACDF57353B8" xml:space="preserve">
-
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- User::LeaveIfError(fs.ShareProtected());
-
- RFile file;
- User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
- CleanupClosePushL(file);
-
- // create test process
- RProcess p;
- User::LeaveIfError(p.Create(_L("FHServer.exe"), KNullDesC));
- CleanupClosePushL(p);
-
- // transfer to process storing the RFs handle into environment slot 1 and the RFile handle into slot 2
- // NB slot 0 is reserved for the command line
- User::LeaveIfError(file.TransferToProcess(p, 1, 2));
-
- // Wait for handle to be transferred; wrap in an active object if blocking this thread is undesirable
- TRequestStatus transStatus;
- p.Rendezvous(transStatus);
-
- if(transStatus != KRequestPending)
- { // Process creation failed
- p.RendezvousCancel(transStatus);
- p.Kill(0);
- User:Leave(transStatus.Int());
- }
- // Start the process
- p.Resume();
-
-
- User::WaitForRequest(transStatus);
- User::LeaveIfError(transfStatus.Int());
-
- // Now we can safely close the fs
- CleanupStack::PopAndDestroy(3); // close p, file, and fs
-
-</codeblock> <p><b>Created process code: </b> </p> <codeblock id="GUID-E429B94F-E373-5F35-A4AC-385732933C23" xml:space="preserve">
-
- RFile file;
-
- // Adopt the file using the RFs handle into environment slot 1 and the RFile handle into slot 2
- User::LeaveIfError(file.AdoptFromCreator(1));
- CleanupClosePushL(file);
- RProcess::Rendezvous(KErrNone); // Signal transfer completed successfully
-
- // ..use the file
- //
-
- CleanupStack::PopAndDestroy(); // close file
-
-</codeblock> </section>
-<section id="GUID-DB2E90FD-5847-54EA-AA40-B7C298AC7801"><title>Implementation
-Considerations</title> <p>An <codeph>RFile</codeph> object contains two handles: </p> <ul>
-<li id="GUID-D724D4E0-5E7F-5208-A55D-395A8C799BB5"><p>a file (or subsession)
-handle </p> </li>
-<li id="GUID-1E73FE27-B147-592C-9C36-D07A266D9805"><p>a file server handle </p> </li>
-</ul> <p>When a file handle is adopted by the <i>receiver</i>, the new <codeph>RFile</codeph> object
-that is created by the <codeph>Adopt***()</codeph> member functions contains
-a duplicate of the sender’s file server handle. This new <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object,
-however, has a flag set in the subsession handle to allow it to close its
-associated file server handle automatically whenever <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-98C413E8-4C84-3DC3-B798-8C25E07EDDFF"><apiname>RFile::Close()</apiname></xref> is
-called. This removes the need to maintain a separate <codeph>RFs</codeph> object
-when adopting a file. </p> <p><b>Security issues </b> </p> <p>It is <i>strongly</i> recommended that the
-process from which a shared file originates, opens a file server session specifically
-for this purpose, and closes it after it has finished using the shared file.
-This is because the session handle is shared along with the file handle, and
-therefore, any other files opened in that session may be accessible to the
-other process. The <i>receiving</i> process can increment file handle numbers
-(remember file handles are only numbers) and gain access to files. </p> <p>It
-is also recommended that the adopting process does not open other files with
-the session it receives, as the process that shared the file may do the same. </p> <p><b>RFs and RFile lifetime issues </b> </p> <p>The <codeph>RFile</codeph> subsession
-handle passed to <codeph>Transfer***()</codeph> and <codeph>Adopt***()</codeph> member
-functions is duplicated by the <codeph>Transfer***()</codeph> functions so
-that the original <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> handle can either be closed immediately
-or used for a period and then closed. This is because it is not the same handle
-as the one being adopted. </p> <p>If there is no need to continue using the <codeph>RFile</codeph> handle,
-then the <codeph>RFs</codeph> handle can be safely closed as follows: </p> <ul>
-<li id="GUID-31668FA4-BC76-52BA-9535-E8ED890C6F83"><p>For <codeph>TransferToServer()</codeph> or <codeph>AdoptFromClient()</codeph>,
-the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the server has
-called <codeph>AdoptFromClient()</codeph>. This would normally be done on
-return from a synchronous call. </p> </li>
-<li id="GUID-F5A80DB7-A09B-516F-9091-A6B3B83489F9"><p>For <codeph>TransferToClient()</codeph> or <codeph>AdoptFromServer()</codeph>,
-the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the server has
-called <codeph>TransferToClient()</codeph>. </p> </li>
-<li id="GUID-85F9159A-25D8-5356-ADE3-048D15B67C13"><p>For <codeph>TransferToProcess()</codeph> or <codeph>AdoptFromCreator()</codeph>,
-the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the client has
-called <codeph>TransferToProcess()</codeph>. </p> </li>
-</ul> </section>
-<section id="GUID-E94C9F16-0F5B-5DCB-B644-A022D26A029C"><title>Testing</title> <p>Extensive
-testing of implementations of this mechanism are not required as, in effect,
-you are simply using a file server subsession (<xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref>) API.
-It is recommended that you test the client-server system, but that will be
-specific to how you use it. If it works you have probably implemented it correctly,
-provided you adhere to the security considerations of the shared file. </p> </section>
-<section id="GUID-061BD238-43D0-5099-95B0-7E811CA59DAF"><title>Summary</title> <p>Passing
-files between processes is a useful tool, but it is important that you adhere
-to the security advice. </p> <p>To share a file handle, take the following
-steps: </p> <ol id="GUID-52469F0B-A94B-5553-8F81-D73590361181">
-<li id="GUID-BA9B1DCC-B185-56FB-B36A-A00BC204B9AD"><p>Ensure the file exists.
-A file to be shared between two processes is a resource that lives in a system
-or private location for security. </p> </li>
-<li id="GUID-439EE193-34F9-527D-BB2F-F1DFC3E90072"><p>Set the fileserver session
-as shareable so that it can be used by more that one process. A fileserver
-session (as with all server sessions) is a Kernel object. </p> </li>
-<li id="GUID-FDFECB4A-991F-5E14-949D-444DE00311D5"><p>Transfer the session
-handle and the subsession handle from the open file using one of the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> <codeph>Transfer***()</codeph> member
-functions and the message passing system between client and server. </p> </li>
-<li id="GUID-3E169BD6-47A7-5275-92B5-08A98BB20B6F"><p>Use one of the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> <codeph>Adopt***()</codeph> member
-functions to begin using the handles in the receiving process. </p> </li>
-<li id="GUID-E0CCBF52-D5CD-5199-8FC8-20DEB6F2F1B6"><p>Once you have finished,
-close the received <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object. </p> </li>
-</ol> </section>
+<?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-E93D3767-0F74-5335-8233-8236908F70AF" xml:lang="en"><title>How
+to share file handles between processes</title><shortdesc>This section describes the sharing of file handles between two
+processes, and the APIs provided for this purpose. This feature is only supported
+on Symbian platform versions with EKA2 architecture. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>It is possible to share file handles between two processes, allowing an
+open file to be passed from one process to another. This is a necessary feature
+in secure versions of Symbian platform. </p>
+<p>Some further implementation considerations are provided to support this
+mechanism. A description of passing file handles is given, followed by examples,
+which show you how to implement a binary using this feature. </p>
+<p> <b>See also</b> </p>
+<p> <xref href="GUID-B69FE02E-3A78-5438-BA7C-F7BB4CD3EB76.dita">File Server Client
+Side Overview</xref> </p>
+<p> <xref href="GUID-4BFEDD79-9502-526A-BA7B-97550A6F0601.dita">Platform security</xref>. </p>
+<p>This section contains the following topics: </p>
+<ul>
+<li id="GUID-79142E0A-C7F1-5545-A152-62C2EF681CC0"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-E5383F93-C846-5A10-BD59-6FE4754FDCD9">Overview</xref> </p> </li>
+<li id="GUID-0CFEA4B0-C2EF-58A0-BE24-A55E695ED6FD"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-16841C97-292A-5EF3-BE88-EE35BF3A0BC8">APIs that support the sharing of file handles</xref> </p> </li>
+<li id="GUID-1B37219E-0980-5B45-8C38-76CD59A8240D"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF">Example 1 - Client passing a file handle to a server</xref> </p> </li>
+<li id="GUID-DFCCFD0E-083E-50CD-9029-AE663311AFC4"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-707872E2-CD5D-5883-A3F5-C66B34C26035">Example 2 - Client requesting a file handle from a server</xref> </p> </li>
+<li id="GUID-A0A1C7DC-177F-5D13-8E89-5952A68D07A2"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-8457BB92-54A3-578B-99AA-0AD5EF8C3068">Example 3 - Client passing a file handle to another process</xref> </p> </li>
+<li id="GUID-167D7C88-4802-57F7-9331-EB6228EC7DDC"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-DB2E90FD-5847-54EA-AA40-B7C298AC7801">Implementation Considerations</xref> </p> </li>
+<li id="GUID-987CE666-F693-5459-9157-AE9CB9DEC9CC"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-E94C9F16-0F5B-5DCB-B644-A022D26A029C">Testing</xref> </p> </li>
+<li id="GUID-B5815E9B-EA0A-5B49-95EF-C010B5D29FFA"><p> <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-061BD238-43D0-5099-95B0-7E811CA59DAF">Summary</xref>. </p> </li>
+</ul>
+<section id="GUID-E5383F93-C846-5A10-BD59-6FE4754FDCD9"><title>Overview</title> <p>Allowing
+an open file to be passed from one process to another is a necessary feature
+in secure versions of Symbian platform. The platform security model provides
+a <i>data caging</i> mechanism, allowing processes and the OS itself to hide
+private data from other processes. </p> <p>However, while it is desirable
+to keep a file safe from other processes, it is useful to give a specific
+process access to the file: </p> <ul>
+<li id="GUID-2553DE33-4C67-5258-862E-00B04CA17EB5"><p>without the need to
+give that process any special capabilities </p> </li>
+<li id="GUID-CB0364D9-2975-5829-ADFF-AD178BF8192C"><p>without the need to
+give the recipient of the file the full path name of that file. </p> </li>
+</ul> <p>New <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> member functions enable an open file
+handle to be passed from client to a server, from server to a client or from
+one process to another process. </p> <p>Note that file handles are not really
+handles in the usual sense of referring to a kernel object, but are simply
+numbers that refer to an open file within a file server session. </p> </section>
+<section id="GUID-16841C97-292A-5EF3-BE88-EE35BF3A0BC8"><title>APIs that support
+the sharing of file handles</title> <p>The following <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> member
+functions support the sharing of file handles between processes: </p> <ul>
+<li id="GUID-C76BE924-7A28-5983-A9D4-05CCECF1B413"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-570BA348-E033-3A63-B702-D2554E95BF0B"><apiname>RFile::AdoptFromClient()</apiname></xref> </p> </li>
+<li id="GUID-EE3FEBF4-6736-5B20-BD9E-21C752239B80"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-2E66E1ED-01FF-3610-BDB7-E83FE1559934"><apiname>RFile::AdoptFromServer()</apiname></xref> </p> </li>
+<li id="GUID-21A5C873-A1F9-595F-92CE-0FE5F27939AE"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-943F64CA-B987-3BF5-B22F-5C637F12EEF4"><apiname>RFile::AdoptFromCreator()</apiname></xref> </p> </li>
+<li id="GUID-972A6339-060D-59E0-94E1-4293A85ED5B2"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-3633606B-09E6-3DD7-8FA3-E20A16CFB87F"><apiname>RFile::TransferToServer()</apiname></xref> </p> </li>
+<li id="GUID-5FF4033F-68F0-5024-8E38-BFF7846661A1"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-B25BF021-8298-397E-9C3B-E4D2E591D88F"><apiname>RFile::TransferToClient()</apiname></xref> </p> </li>
+<li id="GUID-ECC89636-84B4-5B0B-8E31-6BE721D09405"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-FBE294F0-28C3-30E5-A6E4-E82699607216"><apiname>RFile::TransferToProcess()</apiname></xref> </p> </li>
+<li id="GUID-ADA3EBCC-25AB-5E3D-B380-0D3BF643578E"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-EF48ADCC-01F7-3680-B090-9856301E3B9D"><apiname>RFile::Name()</apiname></xref> </p> </li>
+<li id="GUID-63B6C3C7-902A-540F-B8DA-ECE10AB8EE5C"><p> <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-88AC4973-622F-350D-9957-8FA5D409B129"><apiname>RFile::Duplicate()</apiname></xref> </p> </li>
+</ul> <p>The owner of an open <xref href="GUID-D3B4DF9D-BC59-36C1-BE81-D5B5591B2C63.dita"><apiname>Rfile</apiname></xref> object uses the <codeph>Transfer***()</codeph> member
+functions to transfer ownership of that object to another process. Note that
+the file-server session must be marked as shareable by calling <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita#GUID-E263C747-946F-35AA-9F1D-41833BD350FC/GUID-7FD79082-9F32-376B-9BFB-914CA704E3FF"><apiname>RFs::ShareProtected()</apiname></xref> before
+any file handles are transferred, otherwise the <codeph>Transfer***()</codeph> functions
+return <xref href="GUID-25493BDC-2D2E-3CC5-A5FE-A36804A4388A.dita"><apiname>KErrBadHandle</apiname></xref>. </p> <p>A receiving process uses
+the <codeph>Adopt***()</codeph> member functions to adopt an <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object
+passed from another process. </p> <p>A receiving process uses the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-EF48ADCC-01F7-3680-B090-9856301E3B9D"><apiname>RFile::Name()</apiname></xref> member
+function to retrieve the file name and extension (but not the path) from the
+adopted <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object. This is needed mainly by recognisers,
+which sometimes examine a file’s extension to determine whether it is valid
+or not. </p> <p>The <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-88AC4973-622F-350D-9957-8FA5D409B129"><apiname>RFile::Duplicate()</apiname></xref> member function
+allows a process to clone a received <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object so that,
+for example, two separate functions or threads in the receiving process can
+read the file independently. </p> <p>As another example, consider a client
+that only grants access to its <i>data caged</i> private area files, to a
+specific system server. The process that opens the file and shares it (using
+one of the <codeph>Transfer***()</codeph> functions) controls read and write
+access to the file, while the corresponding client or server simply calls
+one of the <codeph>Adopt***()</codeph> functions. In effect, the <codeph>Adopt***()</codeph> functions
+behave like a file opening API such as <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-D5DCA731-EEC7-395A-91EC-2848DFBF5EF8"><apiname>RFile::temp()</apiname></xref>, <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-1EB4AA8F-9363-3EC5-8AE2-1F70F15FCF15"><apiname>RFile::Create()</apiname></xref> and <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-72470A68-7E07-30EF-A3C8-AA855CDAF60E"><apiname>RFile::Open()</apiname></xref>.
+The adopted file retains the access attributes of the file set by the process
+doing the sharing. The access attributes of the file can be changed by the
+adopting process if the security model permits it. </p> <p>The following sections
+present example code and describe how to share a file between two processes.
+This example code uses a simple server that offers the kind of APIs required
+to implement the sharing. Details of this server are not given. </p> <p>Note
+that for the sake of clarity, there is no error checking in the example code. </p> </section>
+<section id="GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF"><title>Example 1 -
+Client passing a file handle to a server</title> <p>In this example, a client
+passes an open file’s handle to a server. The server in turn passes the handle
+over to a second server. </p> <p>The example assumes that the paths and files
+used exist and are correct. A file server session (it is recommended that
+this session is used specifically for this purpose) is set as <i>shared</i> by
+calling <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita#GUID-E263C747-946F-35AA-9F1D-41833BD350FC/GUID-7FD79082-9F32-376B-9BFB-914CA704E3FF"><apiname>RFs::ShareProtected()</apiname></xref>. This enables the session
+to be used by another process. The file is then opened (it exists in the client’s
+private directory). The subsession handle and the fileserver session are then
+passed to the server using <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-3633606B-09E6-3DD7-8FA3-E20A16CFB87F"><apiname>RFile::TransferToServer()</apiname></xref>. The
+file handle can now be adopted by the server’s process. </p> <p><b>Client code: </b> </p> <codeblock id="GUID-D31EA6BD-53F3-5DF8-A447-96C1E99564AE" xml:space="preserve">
+
+ RFileHandleSharer handsvr; // handle to server1
+ User::LeaveIfError(handsvr.Connect()); // connect to server1
+ CleanupClosePushL(handsvr);
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.ShareProtected());
+
+ RFile file;
+ User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
+ CleanupClosePushL(file);
+
+
+ // store the RFs handle in message slot 0 and the RFile handle in slot 1
+ TIpcArgs ipcArgs;
+ User::LeaveIfError(file.TransferToServer(ipcArgs, 0, 1));
+
+ // send to server
+ User::LeaveIfError(handsvr.SendReceive(EMsgXXX, ipcArgs));
+
+ // ...continue to use file
+ //
+
+ CleanupStack::PopAndDestroy(3); // close file, fs, and handsvr
+</codeblock> <p><b>Server1 code: </b> </p> <codeblock id="GUID-73CA766C-FE29-56C1-94C3-2FC23CAC910E" xml:space="preserve">
+
+ void CFHSession::PassFileHandleL(const RMessage2& aMsg)
+ {
+ RFileHandleSharer2 handsvr2; // connect to server2
+ User::LeaveIfError(handsvr2.Connect());
+ CleanupClosePushL(handsvr2);
+
+ RFile file;
+
+ // Adopt the file using the RFs handle from message slot 0 and the RFile handle from slot 1
+ User::LeaveIfError(file.AdoptFromClient(aMsg, 0, 1));
+ CleanupClosePushL(file);
+
+ // Use the file
+ // …
+
+
+ // pass the file handle on to server2
+ TIpcArgs ipcArgs;
+ User::LeaveIfError(file.TransferToServer(ipcArgs, 0, 1));
+ User::LeaveIfError(handsvr2.SendReceive(EMsgXXX, ipcArgs));
+
+ // continue to use file
+ // …
+
+ CleanupStack::PopAndDestroy(2); // close file and handsvr2
+
+ aMsg.Complete(KErrNone);
+ }
+
+</codeblock> <p><b>Server2 code: </b> </p> <codeblock id="GUID-A48D53BF-9616-5CBD-91FD-588D1EED71F7" xml:space="preserve">
+
+ void CFHSession2::PassFileHandleL(const RMessage2& aMsg)
+ {
+ RFile file;
+
+ // Adopt the file using the RFs handle from message slot 0 and the RFile handle from slot 1
+ User::LeaveIfError(file.AdoptFromClient(aMsg, 0, 1));
+ CleanupClosePushL(file);
+
+ // ..use the file
+
+ CleanupStack::PopAndDestroy(); // close file
+
+ aMsg.Complete(KErrNone);
+ }
+
+</codeblock> </section>
+<section id="GUID-707872E2-CD5D-5883-A3F5-C66B34C26035"><title>Example 2 -
+Client requesting a file handle from a server</title> <p>This example is similar
+to <xref href="GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita#GUID-E93D3767-0F74-5335-8233-8236908F70AF/GUID-B8F732D9-C97F-59FD-9623-E9D14EE657EF">Example
+1</xref> but there are some differences. </p> <p>A client connects to a server
+that provides a shared fileserver session and a file handle to an open file
+when requested. </p> <p><b>Client code: </b> </p> <codeblock id="GUID-D93672C4-9FBA-543F-8C2B-5F7ABFCC2A50" xml:space="preserve">
+
+ RFileHandleSharer handsvr; // handle to server
+ User::LeaveIfError(handsvr.Connect()); // connect to server
+ CleanupClosePushL(handsvr);
+
+ // Retrieve the RFs and RFile handles from the server
+ TInt fsh; // session (RFs) handle
+ TPckgBuf<TInt> fh; // sub-session (RFile) handle
+
+ fsh = handsvr.SendReceive(EMsgXXX, TIpcArgs(&fh)); // pointer to fh in slot 0
+ User::LeaveIfError(fsh);
+
+// Adopt the file using the returned handles
+RFile file;
+User::LeaveIfError(file.AdoptFromServer(fsh, fh()));
+ CleanupClosePushL(file);
+
+// ..use the file
+//
+
+ CleanupStack::PopAndDestroy(2); // close file and handsvr
+
+</codeblock> <p><b>Server code: </b> </p> <codeblock id="GUID-4A16D8FB-C235-5DE6-A8E3-A7042DDCBBD4" xml:space="preserve">
+
+ void CFHSession::GetFileHandleL(const RMessage2& aMsg)
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ User::LeaveIfError(fs.ShareProtected());
+
+ RFile file;
+ User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
+
+ // transfer to client: store the RFile handle into the package buffer in slot 0
+ // and complete the message with the RFs handle
+ // NB this assumes that if TransferToClient() return an error, then
+ // the standard CServer2::RunError() will complete the message
+ User::LeaveIfError(file.TransferToClient(aMsg, 0));
+ ASSERT(aMsg.IsNull()); // message should have been completed
+
+ file.Close();
+ CleanupStack::PopAndDestroy(1); // fs
+ }
+
+</codeblock> </section>
+<section id="GUID-8457BB92-54A3-578B-99AA-0AD5EF8C3068"><title>Example 3 -
+Client passing a file handle to another process</title> <p><b>Creator code: </b> </p> <codeblock id="GUID-92F72808-9A52-5504-8580-EACDF57353B8" xml:space="preserve">
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ User::LeaveIfError(fs.ShareProtected());
+
+ RFile file;
+ User::LeaveIfError(file.Open(fs, _L("test.txt"), EFileRead));
+ CleanupClosePushL(file);
+
+ // create test process
+ RProcess p;
+ User::LeaveIfError(p.Create(_L("FHServer.exe"), KNullDesC));
+ CleanupClosePushL(p);
+
+ // transfer to process storing the RFs handle into environment slot 1 and the RFile handle into slot 2
+ // NB slot 0 is reserved for the command line
+ User::LeaveIfError(file.TransferToProcess(p, 1, 2));
+
+ // Wait for handle to be transferred; wrap in an active object if blocking this thread is undesirable
+ TRequestStatus transStatus;
+ p.Rendezvous(transStatus);
+
+ if(transStatus != KRequestPending)
+ { // Process creation failed
+ p.RendezvousCancel(transStatus);
+ p.Kill(0);
+ User:Leave(transStatus.Int());
+ }
+ // Start the process
+ p.Resume();
+
+
+ User::WaitForRequest(transStatus);
+ User::LeaveIfError(transfStatus.Int());
+
+ // Now we can safely close the fs
+ CleanupStack::PopAndDestroy(3); // close p, file, and fs
+
+</codeblock> <p><b>Created process code: </b> </p> <codeblock id="GUID-E429B94F-E373-5F35-A4AC-385732933C23" xml:space="preserve">
+
+ RFile file;
+
+ // Adopt the file using the RFs handle into environment slot 1 and the RFile handle into slot 2
+ User::LeaveIfError(file.AdoptFromCreator(1));
+ CleanupClosePushL(file);
+ RProcess::Rendezvous(KErrNone); // Signal transfer completed successfully
+
+ // ..use the file
+ //
+
+ CleanupStack::PopAndDestroy(); // close file
+
+</codeblock> </section>
+<section id="GUID-DB2E90FD-5847-54EA-AA40-B7C298AC7801"><title>Implementation
+Considerations</title> <p>An <codeph>RFile</codeph> object contains two handles: </p> <ul>
+<li id="GUID-D724D4E0-5E7F-5208-A55D-395A8C799BB5"><p>a file (or subsession)
+handle </p> </li>
+<li id="GUID-1E73FE27-B147-592C-9C36-D07A266D9805"><p>a file server handle </p> </li>
+</ul> <p>When a file handle is adopted by the <i>receiver</i>, the new <codeph>RFile</codeph> object
+that is created by the <codeph>Adopt***()</codeph> member functions contains
+a duplicate of the sender’s file server handle. This new <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object,
+however, has a flag set in the subsession handle to allow it to close its
+associated file server handle automatically whenever <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita#GUID-BE0804F6-4375-3C8A-8C83-968F510466E0/GUID-98C413E8-4C84-3DC3-B798-8C25E07EDDFF"><apiname>RFile::Close()</apiname></xref> is
+called. This removes the need to maintain a separate <codeph>RFs</codeph> object
+when adopting a file. </p> <p><b>Security issues </b> </p> <p>It is <i>strongly</i> recommended that the
+process from which a shared file originates, opens a file server session specifically
+for this purpose, and closes it after it has finished using the shared file.
+This is because the session handle is shared along with the file handle, and
+therefore, any other files opened in that session may be accessible to the
+other process. The <i>receiving</i> process can increment file handle numbers
+(remember file handles are only numbers) and gain access to files. </p> <p>It
+is also recommended that the adopting process does not open other files with
+the session it receives, as the process that shared the file may do the same. </p> <p><b>RFs and RFile lifetime issues </b> </p> <p>The <codeph>RFile</codeph> subsession
+handle passed to <codeph>Transfer***()</codeph> and <codeph>Adopt***()</codeph> member
+functions is duplicated by the <codeph>Transfer***()</codeph> functions so
+that the original <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> handle can either be closed immediately
+or used for a period and then closed. This is because it is not the same handle
+as the one being adopted. </p> <p>If there is no need to continue using the <codeph>RFile</codeph> handle,
+then the <codeph>RFs</codeph> handle can be safely closed as follows: </p> <ul>
+<li id="GUID-31668FA4-BC76-52BA-9535-E8ED890C6F83"><p>For <codeph>TransferToServer()</codeph> or <codeph>AdoptFromClient()</codeph>,
+the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the server has
+called <codeph>AdoptFromClient()</codeph>. This would normally be done on
+return from a synchronous call. </p> </li>
+<li id="GUID-F5A80DB7-A09B-516F-9091-A6B3B83489F9"><p>For <codeph>TransferToClient()</codeph> or <codeph>AdoptFromServer()</codeph>,
+the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the server has
+called <codeph>TransferToClient()</codeph>. </p> </li>
+<li id="GUID-85F9159A-25D8-5356-ADE3-048D15B67C13"><p>For <codeph>TransferToProcess()</codeph> or <codeph>AdoptFromCreator()</codeph>,
+the <xref href="GUID-E263C747-946F-35AA-9F1D-41833BD350FC.dita"><apiname>RFs</apiname></xref> handle can be safely closed once the client has
+called <codeph>TransferToProcess()</codeph>. </p> </li>
+</ul> </section>
+<section id="GUID-E94C9F16-0F5B-5DCB-B644-A022D26A029C"><title>Testing</title> <p>Extensive
+testing of implementations of this mechanism are not required as, in effect,
+you are simply using a file server subsession (<xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref>) API.
+It is recommended that you test the client-server system, but that will be
+specific to how you use it. If it works you have probably implemented it correctly,
+provided you adhere to the security considerations of the shared file. </p> </section>
+<section id="GUID-061BD238-43D0-5099-95B0-7E811CA59DAF"><title>Summary</title> <p>Passing
+files between processes is a useful tool, but it is important that you adhere
+to the security advice. </p> <p>To share a file handle, take the following
+steps: </p> <ol id="GUID-52469F0B-A94B-5553-8F81-D73590361181">
+<li id="GUID-BA9B1DCC-B185-56FB-B36A-A00BC204B9AD"><p>Ensure the file exists.
+A file to be shared between two processes is a resource that lives in a system
+or private location for security. </p> </li>
+<li id="GUID-439EE193-34F9-527D-BB2F-F1DFC3E90072"><p>Set the fileserver session
+as shareable so that it can be used by more that one process. A fileserver
+session (as with all server sessions) is a Kernel object. </p> </li>
+<li id="GUID-FDFECB4A-991F-5E14-949D-444DE00311D5"><p>Transfer the session
+handle and the subsession handle from the open file using one of the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> <codeph>Transfer***()</codeph> member
+functions and the message passing system between client and server. </p> </li>
+<li id="GUID-3E169BD6-47A7-5275-92B5-08A98BB20B6F"><p>Use one of the <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> <codeph>Adopt***()</codeph> member
+functions to begin using the handles in the receiving process. </p> </li>
+<li id="GUID-E0CCBF52-D5CD-5199-8FC8-20DEB6F2F1B6"><p>Once you have finished,
+close the received <xref href="GUID-BE0804F6-4375-3C8A-8C83-968F510466E0.dita"><apiname>RFile</apiname></xref> object. </p> </li>
+</ol> </section>
</conbody></concept>
\ No newline at end of file