internal HResult GetFileDataCallback()

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;
        }