kRdrFile-iprt.cpp revision c7814cf6e1240a519cbec0441e033d0e2470ed00
/* $Id$ */
/** @file
* IPRT - kRdr Backend.
*/
/*
* Copyright (C) 2007-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Prepared stuff.
*/
typedef struct KRDRFILEPREP
{
/** The address of the prepared region. */
void *pv;
/** The size of the prepared region. */
/**
* The file provier instance for native files.
*/
typedef struct KRDRFILE
{
/** The file reader vtable. */
/** The file handle. */
/** The current file offset. */
/** The file size. */
/** Array where we stuff the mapping area data. */
/** The number of current preps. */
/** Number of mapping references. */
/** The memory mapping. */
void *pvMapping;
/** The filename. */
char szFilename[1];
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static int krdrRTFileGenericUnmap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments);
static int krdrRTFileProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
static int krdrRTFileGenericProtect(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
static int krdrRTFileGenericRefresh(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments);
static int krdrRTFileMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
static int krdrRTFileGenericMap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** Native file provider operations. */
const KRDROPS g_kRdrFileOps =
{
"IPRT file",
NULL,
42
};
/** @copydoc KRDROPS::pfnDone */
{
}
/**
* Finds a prepared mapping region.
*
* @returns Pointer to the aPrep entry.
* @param pFile The instance data.
* @param pv The base of the region.
*/
{
while (i-- > 0)
return NULL;
}
/** @copydoc KRDROPS::pfnUnmap */
{
int rc;
if (!pPrep)
return KERR_INVALID_PARAMETER;
/* remove the mapping data on success. */
if (!rc)
{
}
return rc;
}
/** Generic implementation of krdrRTFileUnmap. */
static int krdrRTFileGenericUnmap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments)
{
return 0;
}
/** @copydoc KRDROPS::pfnProtect */
static int krdrRTFileProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
{
if (!pPrep)
return KERR_INVALID_PARAMETER;
}
{
switch (enmProt)
{
case KPROT_NOACCESS: return RTMEM_PROT_NONE;
case KPROT_READONLY: return RTMEM_PROT_READ;
case KPROT_EXECUTE: return RTMEM_PROT_EXEC;
default:
AssertFailed();
return ~0U;
}
}
/** Generic implementation of krdrRTFileProtect. */
static int krdrRTFileGenericProtect(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
{
KU32 i;
/*
* Iterate the segments and apply memory protection changes.
*/
for (i = 0; i < cSegments; i++)
{
int rc;
void *pv;
continue;
/* calc new protection. */
if (fUnprotectOrProtect)
{
switch (enmProt)
{
case KPROT_NOACCESS:
case KPROT_READONLY:
case KPROT_READWRITE:
case KPROT_WRITECOPY:
break;
case KPROT_EXECUTE:
case KPROT_EXECUTE_READ:
case KPROT_EXECUTE_READWRITE:
case KPROT_EXECUTE_WRITECOPY:
break;
default:
AssertFailed();
return -1;
}
}
else
{
/* copy on write -> normal write. */
if (enmProt == KPROT_EXECUTE_WRITECOPY)
else if (enmProt == KPROT_WRITECOPY)
}
if (rc)
break;
}
return 0;
}
/** @copydoc KRDROPS::pfnRefresh */
{
if (!pPrep)
return KERR_INVALID_PARAMETER;
}
/** Generic implementation of krdrRTFileRefresh. */
static int krdrRTFileGenericRefresh(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments)
{
int rc;
int rc2;
KU32 i;
/*
* Make everything writable again.
*/
if (rc)
{
return rc;
}
/*
* Clear everything.
*/
/** @todo only zero the areas not covered by raw file bits. */
/*
* Reload all the segments.
* We could possibly skip some segments, but we currently have
* no generic way of figuring out which at the moment.
*/
for (i = 0; i < cSegments; i++)
{
void *pv;
|| paSegments[i].cbFile <= 0)
continue;
if (rc)
break;
}
/*
* Protect the bits again.
*/
return rc;
}
/** @copydoc KRDROPS::pfnMap */
static int krdrRTFileMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
{
int rc;
KU32 i;
return KRDR_ERR_TOO_MANY_MAPPINGS;
/*
* Calc the total mapping space needed.
*/
cbTotal = 0;
for (i = 0; i < cSegments; i++)
{
continue;
if (cbTotal < uRVASegmentEnd)
}
return KLDR_ERR_ADDRESS_OVERFLOW;
/*
* Use the generic map emulation.
*/
if (!rc)
{
}
return rc;
}
/** Generic implementation of krdrRTFileMap. */
static int krdrRTFileGenericMap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
{
int rc = 0;
KU32 i;
/*
* Generic mapping code using kHlpPageAlloc(), kHlpPageFree() and kHlpPageProtect().
*/
return KERR_NO_MEMORY;
/*
* Load the data.
*/
for (i = 0; i < cSegments; i++)
{
void *pv;
|| paSegments[i].cbFile <= 0)
continue;
if (rc)
break;
}
/*
* Set segment protection.
*/
if (!rc)
{
if (!rc)
return 0;
}
/* bailout */
return rc;
}
/** @copydoc KRDROPS::pfnPageSize */
{
return PAGE_SIZE;
}
/** @copydoc KRDROPS::pfnName */
{
return &pRdrFile->szFilename[0];
}
{
}
/** @copydoc KRDROPS::pfnTell */
{
/*
* If the offset is undefined, try figure out what it is.
*/
{
}
}
/** @copydoc KRDROPS::pfnSize */
{
}
/** @copydoc KRDROPS::pfnAllUnmap */
{
/* check for underflow */
return KERR_INVALID_PARAMETER;
/* decrement usage counter, free mapping if no longer in use. */
{
}
return 0;
}
/** @copydoc KRDROPS::pfnAllMap */
{
/*
* Do we need to map it?
*/
{
int rc;
return KERR_NO_MEMORY;
return KERR_NO_MEMORY;
if (rc)
{
return rc;
}
}
return 0;
}
/** @copydoc KRDROPS::pfnRead */
{
int rc;
/*
* Do a seek if needed.
*/
{
if (RT_FAILURE(rc))
{
return rc;
}
}
/*
* Do the read.
*/
if (RT_FAILURE(rc))
{
return rc;
}
return 0;
}
/** @copydoc KRDROPS::pfnDestroy */
{
int rc;
{
}
return rc;
}
/** @copydoc KRDROPS::pfnCreate */
{
int rc;
char szFilename[RTPATH_MAX];
/*
* Open the file, determin its size and correct filename.
*/
if (RT_FAILURE(rc))
return rc;
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/*
* Allocate the reader instance.
*/
if (pRdrFile)
{
/*
* Initialize it and return successfully.
*/
return 0;
}
rc = KERR_NO_MEMORY;
}
}
return rc;
}