in simpleProviderManaged/SimpleProvider.cs [546:629]
internal HResult GetFileDataCallback(
int commandId,
string relativePath,
ulong byteOffset,
uint length,
Guid dataStreamId,
byte[] contentId,
byte[] providerId,
uint triggeringProcessId,
string triggeringProcessImageFileName)
{
Log.Information("----> GetFileDataCallback relativePath [{Path}]", relativePath);
Log.Information(" triggered by [{ProcName} {PID}]", triggeringProcessImageFileName, triggeringProcessId);
HResult hr = HResult.Ok;
if (!this.FileExistsInLayer(relativePath))
{
hr = HResult.FileNotFound;
}
else
{
// We'll write the file contents to ProjFS no more than 64KB at a time.
uint desiredBufferSize = Math.Min(64 * 1024, length);
try
{
// We could have used VirtualizationInstance.CreateWriteBuffer(uint), but this
// illustrates how to use its more complex overload. This method gets us a
// buffer whose underlying storage is properly aligned for unbuffered I/O.
using (IWriteBuffer writeBuffer = this.virtualizationInstance.CreateWriteBuffer(
byteOffset,
desiredBufferSize,
out ulong alignedWriteOffset,
out uint alignedBufferSize))
{
// Get the file data out of the layer and write it into ProjFS.
hr = this.HydrateFile(
relativePath,
alignedBufferSize,
(readBuffer, bytesToCopy) =>
{
// readBuffer contains what HydrateFile() read from the file in the
// layer. Now seek to the beginning of the writeBuffer and copy the
// contents of readBuffer into writeBuffer.
writeBuffer.Stream.Seek(0, SeekOrigin.Begin);
writeBuffer.Stream.Write(readBuffer, 0, (int)bytesToCopy);
// Write the data from the writeBuffer into the scratch via ProjFS.
HResult writeResult = this.virtualizationInstance.WriteFileData(
dataStreamId,
writeBuffer,
alignedWriteOffset,
bytesToCopy);
if (writeResult != HResult.Ok)
{
Log.Error("VirtualizationInstance.WriteFileData failed: {Result}", writeResult);
return false;
}
alignedWriteOffset += bytesToCopy;
return true;
});
if (hr != HResult.Ok)
{
return HResult.InternalError;
}
}
}
catch (OutOfMemoryException e)
{
Log.Error(e, "Out of memory");
hr = HResult.OutOfMemory;
}
catch (Exception e)
{
Log.Error(e, "Exception");
hr = HResult.InternalError;
}
}
Log.Information("<---- return status {Result}", hr);
return hr;
}