Symbian3/SDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita
changeset 7 51a74ef9ed63
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita	Wed Mar 31 11:11:55 2010 +0100
@@ -0,0 +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&amp; 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&amp; 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&lt;TInt&gt; fh;    // sub-session (RFile) handle
+    
+    fsh = handsvr.SendReceive(EMsgXXX, TIpcArgs(&amp;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&amp; 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