private static LuigiFileHeader GetLuigiHeaderForFork(ExecuteDeviceCommandAsyncTaskData data, Fork fork)
        {
            LuigiFileHeader luigiHeader = null;

            using (var memory = new System.IO.MemoryStream())
            {
                const uint Address     = 0u;
                var        bytesToRead = LuigiFileHeader.MaxHeaderSize;
                var        succeeded   = ReadForkToRam.Create(Address, fork.GlobalForkNumber, 0u, bytesToRead).Execute <bool>(data.Device.Port, data);
                byte[]     dataRead    = null;
                if (succeeded)
                {
                    dataRead = (byte[])DownloadDataBlockFromRam.Create(Address, bytesToRead).Execute(data.Device.Port, data, out succeeded);
                }
                if (succeeded)
                {
                    memory.Write(dataRead, 0, bytesToRead);
                    memory.Seek(0, System.IO.SeekOrigin.Begin);
                    try
                    {
                        luigiHeader = LuigiFileHeader.Inflate(memory);
                    }
                    catch (INTV.Core.UnexpectedFileTypeException)
                    {
                    }
                }
            }
            return(luigiHeader);
        }
        private static bool RetrieveForkData(this Device device, ExecuteDeviceCommandAsyncTaskData data, IEnumerable <Fork> forksToRetrieve, string destinationDirectory, IEnumerable <string> fileNames)
        {
            var configuration      = SingleInstanceApplication.Instance.GetConfiguration <Configuration>();
            var succeeded          = false;
            var numForks           = forksToRetrieve.Count();
            var forkFilenames      = fileNames == null ? null : fileNames.ToList();
            var forkBeingRetrieved = 0;

            foreach (var fork in forksToRetrieve)
            {
                if (data.AcceptCancelIfRequested())
                {
                    break;
                }
                ++forkBeingRetrieved;
                if (data != null)
                {
                    data.UpdateTaskProgress((double)forkBeingRetrieved / numForks, string.Format(Resources.Strings.DeviceMultistageCommand_BackupFileSystem_RetrievingFiles_Format, forkBeingRetrieved, numForks));
                }
                var bytesRemaining = (int)fork.Size;
                var offset         = 0;
                succeeded = false;
                using (var memory = new System.IO.MemoryStream())
                {
                    do
                    {
                        const uint Address     = 0u;
                        var        bytesToRead = System.Math.Min(bytesRemaining, Device.TotalRAMSize);
                        succeeded = ReadForkToRam.Create(Address, fork.GlobalForkNumber, (uint)offset, bytesToRead).Execute <bool>(device.Port, data);
                        byte[] dataRead = null;
                        if (succeeded)
                        {
                            dataRead = (byte[])DownloadDataBlockFromRam.Create(Address, bytesToRead).Execute(device.Port, data, out succeeded);
                        }
                        if (succeeded)
                        {
                            memory.Write(dataRead, offset, bytesToRead);
                            bytesRemaining -= bytesToRead;
                            offset         += bytesToRead;
                        }
                    }while (succeeded && (bytesRemaining > 0));

                    if (data != null)
                    {
                        data.UpdateTaskProgress((double)forkBeingRetrieved / numForks, string.Format(Resources.Strings.DeviceMultistageCommand_BackupFileSystem_SavingFiles_Format, forkBeingRetrieved, numForks));
                    }
                    memory.Seek(0, System.IO.SeekOrigin.Begin);
                    using (var tempFile = FileSystemFile.Inflate(memory))
                    {
                        var fileName = (forkFilenames == null) ? configuration.GetForkDataFileName(fork.GlobalForkNumber) : forkFilenames[forkBeingRetrieved - 1];
                        var forkPath = System.IO.Path.Combine(destinationDirectory, fileName);
                        forkPath            = forkPath.EnsureUniqueFileName();
                        data.FailureMessage = forkPath;
                        System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(forkPath));
                        try
                        {
                            // Test to see if this is a Fork containing a LUIGI file.
                            memory.Seek(0, System.IO.SeekOrigin.Begin);
                            LuigiFileHeader.Inflate(memory);
                            forkPath = System.IO.Path.ChangeExtension(forkPath, ProgramFileKind.LuigiFile.FileExtension());
                        }
                        catch (INTV.Core.UnexpectedFileTypeException)
                        {
                            // This is OK... we only want to execute certain functions if the file is a LUIGI file.
                        }
                        if (System.IO.File.Exists(forkPath))
                        {
                            var crcOfTarget = Crc32.OfFile(forkPath);
                            var crcOfSource = Crc32.OfFile(tempFile.FileInfo.FullName);
                            if (crcOfTarget != crcOfSource)
                            {
                                forkPath = forkPath.EnsureUniqueFileName();
                                System.IO.File.Copy(tempFile.FileInfo.FullName, forkPath);
                            }
                        }
                        else
                        {
                            System.IO.File.Copy(tempFile.FileInfo.FullName, forkPath);
                        }
                        fork.FilePath = forkPath;
                    }
                }
                if (!succeeded)
                {
                    break;
                }
            }
            return(succeeded);
        }