Symbian3/SDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita
changeset 0 89d6a7a84779
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita	Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept xml:lang="en" id="GUID-E93D3767-0F74-5335-8233-8236908F70AF"><title>How to share file handles between processes</title><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 OS. </p> <p>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 OS versions with EKA2 architecture. </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 OS. 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