Symbian3/SDK/Source/GUID-E93D3767-0F74-5335-8233-8236908F70AF.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 7 51a74ef9ed63
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?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>