Example #1
0
        void RetryTitleKeys(DVDDecryption dvdDecrypt, byte[] discKey, ref double totalDuration)
        {
            int  pass    = 1;
            bool forward = true;
            bool sense;

            byte[] buffer;

            InitProgress?.Invoke();

repeatRetry:
            ulong[] tmpArray = _resume.MissingTitleKeys.ToArray();

            foreach (ulong missingKey in tmpArray)
            {
                if (_aborted)
                {
                    UpdateStatus?.Invoke("Aborted!");
                    _dumpLog.WriteLine("Aborted!");

                    break;
                }

                PulseProgress?.Invoke(string.Format("Retrying title key {0}, pass {1}, {2}", missingKey, pass,
                                                    forward ? "forward" : "reverse"));

                sense = dvdDecrypt.ReadTitleKey(out buffer, out _, DvdCssKeyClass.DvdCssCppmOrCprm, missingKey,
                                                _dev.Timeout, out double cmdDuration);

                totalDuration += cmdDuration;

                if (!sense &&
                    !_dev.Error)
                {
                    CSS_CPRM.TitleKey?titleKey = CSS.DecodeTitleKey(buffer, dvdDecrypt.BusKey);

                    if (titleKey.HasValue)
                    {
                        _outputPlugin.WriteSectorTag(new[]
                        {
                            titleKey.Value.CMI
                        }, missingKey, SectorTagType.DvdCmi);

                        // If the CMI bit is 1, the sector is using copy protection, else it is not
                        // If the decoded title key is zeroed, there should be no copy protection
                        if ((titleKey.Value.CMI & 0x80) >> 7 == 0 ||
                            titleKey.Value.Key.All(k => k == 0))
                        {
                            _outputPlugin.WriteSectorTag(new byte[]
                            {
                                0, 0, 0, 0, 0
                            }, missingKey, SectorTagType.DvdTitleKey);

                            _outputPlugin.WriteSectorTag(new byte[]
                            {
                                0, 0, 0, 0, 0
                            }, missingKey, SectorTagType.DvdTitleKeyDecrypted);

                            _resume.MissingTitleKeys.Remove(missingKey);
                            UpdateStatus?.Invoke($"Correctly retried title key {missingKey} in pass {pass}.");
                            _dumpLog.WriteLine("Correctly retried title key {0} in pass {1}.", missingKey, pass);
                        }
                        else
                        {
                            _outputPlugin.WriteSectorTag(titleKey.Value.Key, missingKey, SectorTagType.DvdTitleKey);
                            _resume.MissingTitleKeys.Remove(missingKey);

                            if (discKey != null)
                            {
                                CSS.DecryptTitleKey(0, discKey, titleKey.Value.Key, out buffer);
                                _outputPlugin.WriteSectorTag(buffer, missingKey, SectorTagType.DvdTitleKeyDecrypted);
                            }

                            UpdateStatus?.Invoke($"Correctly retried title key {missingKey} in pass {pass}.");
                            _dumpLog.WriteLine("Correctly retried title key {0} in pass {1}.", missingKey, pass);
                        }
                    }
                }
            }

            if (pass < _retryPasses &&
                !_aborted &&
                _resume.MissingTitleKeys.Count > 0)
            {
                pass++;
                forward = !forward;
                _resume.MissingTitleKeys.Sort();

                if (!forward)
                {
                    _resume.MissingTitleKeys.Reverse();
                }

                goto repeatRetry;
            }

            EndProgress?.Invoke();
        }