Pull to refresh

Об одной проблеме запуска Архивации и Восстановления при использовании OpenSource кода с сайта CodeGuru

Lumber room


Работаю в техподдержке, в один прекрасный день столкнулся с проблемой запуска Архивации или Восстановления в Windows 7. У пользователя на компьютере при выборе в «Панели управления» вкладки «Архивация или восстановление» перестало работать нажатие на «Настроить резервное копирование». Чтобы не искать вкладку, можете просто запустить программу C:\Windows\System32\sdclt.exe

Поиск решения проблемы через Yandex/Google ни к чему не привел. О проблеме много говорят, но реально никто не знает, что происходит, кроме того, что советуют деинсталлировать CompareIt! или PowerISO, которые некорректно обрабатывают встраивание в Проводник через Shell Context Menu. Начал проверять, нет ли похожих программ в нашем случае и выяснилось, что действительно, недавно была инсталлирована одна полезная утилита, которая меняет контекстное меню Проводника, расширяя его возможности.

После деинсталляции этой программы проблемы с Архивацией исчезли. Обратился в техподдержку, меня переключили на разработчиков, которые ничего внятного сказать не могли, кроме того, что утилита была написана достаточно давно и не предназначена для работы с Windows 7. Кроме того, в приватной беседе выяснилось, что для встраивания в Shell Context Menu был использован OpenSource код с сайта CodeGuru.

CtxMenu, Copyright 1999, Smaller Animals Software
This code may be modifed and distributed free of charge or restrictions.
This code is provided as-is. If you use this code in any application, any bugs in the code are your responsibility.


Что же на самом деле происходит?

Как ни странно, ноги растут именно с сайта CodeGuru, где еще в 1999 году Chris Losinger опубликовал свою статью, содержащую пример работы с ContextMenu, которая впоследствии широко разошлась по просторам Интернета. Подозреваю, что вышеуказанные проблемы CompareIt! и PowerISO также связаны с использованием этого кода.

Рассмотрим подробнее файл ShellCtxMenu.cpp, функция InvokeCommand:

STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
//
//немного кода skipped
//
    HRESULT hr = NOERROR;

    if (!HIWORD(lpcmi->lpVerb)) 
    {
         idCmd = LOWORD(lpcmi->lpVerb);

         // process it
         switch (idCmd) 
         {
                default:
                case 0: // operation 1
                case 1: // operation 2
//
//много кода skipped
//
                break;
         }    // switch on command
    }

   return hr;
}


Легко увидеть, что внутри switch обработка ветки default и других case происходит одинаково, а в конце функции всегда возвращается NOERROR. Это неправильно. А где же код возврата E_INVALIDARG — его нужно обязательно использовать, чтобы просигнализировать, что мы не обработали idCmd.

Меняем код на такой:

STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
//
//немного кода skipped
//
    HRESULT hr = E_INVALIDARG;

    if (!HIWORD(lpcmi->lpVerb)) 
    {
         idCmd = LOWORD(lpcmi->lpVerb);

         // process it
         switch (idCmd) 
         {
                default:
                    goto err_exit;
                case 0: // operation 1
                case 1: // operation 2
//
//много кода skipped
//
                break;
         }    // switch on command
         hr = NOERROR;
    }
err_exit:
   return hr;
}


В этом случае возвращаем E_INVALIDARG, если это не наша команда или NOERROR — если наша и она была обработана. После этих изменений средство Архивации или Восстановления стало работать корректно.

Напомню, что готовый файл CtxMenu.Dll следует зарегистрировать путем вызова команды «regsvr32.exe CtxMenu.Dll» под Администратором, деинициализация и удаление из Context Menu Проводника должна выполняться с ключом /u посредством «regsvr32.exe /u CtxMenu.Dll».

Добавлю, что в английском варианте Windows 7 средство «Архивация или Восстановление» пункт «Настроить резервное копирование» называются «Backup and Restore» и «Set up backup» соответственно.

Спасибо за внимание.
Tags:
Hubs:
Total votes 28: ↑22 and ↓6 +16
Views 5.8K
Comments Comments 15