Как формируется ShellState

Тема в разделе "Реестр Microsoft Windows", создана пользователем bob_plus, 24 ноя 2017.

Метки:
  1. bob_plus

    bob_plus Новый пользователь

    Сообщения:
    12
    Симпатии:
    2
    Попробовал порулить по мелочи (сделать переключение "открывать одним кликом" из скрипта ) параметром ShellState из ветки HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer. "Мордой об забор"...:Wacko:.
    Пролистал разные сборки Win7 c одними настройками - везде разные ключи:
    Se7en
    32 - 0 240000003ca8010000000000000000000000000001000000120000000000000032000000
    32 - 1 240000001ca8010000000000000000000000000001000000120000000000000032000000
    Se7en32
    240000001728010000000000000000000000000001000000120000000000000022000000
    Se7en64_55
    240000001728010000000000000000000000000001000000120000000000000022000000
    32pro
    240000001828000000000000000000000000000001000000120000000000000022000000
    Pro
    64 - 0 2400000033a8000000000000000000000000000001000000120000000000000032000000
    64 - 1 2400000013a8000000000000000000000000000001000000120000000000000032000000
    240000001828000000000000000000000000000001000000120000000000000022000000
    64max
    240000001828000000000000000000000000000001000000120000000000000022000000

    Кто-нибудь пробовал "играться" с этим ключем?

    И как он вообще формируется?
     
    Последнее редактирование: 24 ноя 2017
  2. Лучший ответ:
    Post #5 by Dragokas, 24 ноя 2017
  3. Dragokas

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    5.341
    Симпатии:
    5.248
    Здравствуйте, bob_plus !

    В целом, структура описана здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/bb759788(v=vs.85).aspx
    У неё особое выравнивание - называется "битовые поля". После двоеточния указано количество бит, занимаемых полем структуры.

    Первое число из реестра, например, в вашем примере 24 - это первый из байтов, записанных в 16-ричной системе счисления.
     
    Последнее редактирование: 24 ноя 2017
    DllPok и Кирилл нравится это.
  4. bob_plus

    bob_plus Новый пользователь

    Сообщения:
    12
    Симпатии:
    2
    Если не сложно: что такое "выравнивание"? По отношению к чему? Про двоеточие - то из справки MSDN?
    Есть представление: как можно трансформировать ключ для тех утилитарных целей, что я описал?
    Есть ли представление как о формируется?
    А потом: 24 - это что? Не в смысле байтов, а что они означают?
     
  5. Dragokas

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    5.341
    Симпатии:
    5.248
    Выравнивание по отношению к границе, в данном случае 4-байтовой, т.е. например, если поля идут в таком порядке:

    BYTE (тип данных занимает 1 байт)
    DWORD (тип данных занимает 4 байт)

    то общий размер структуры займёт не 5 байт, а 8, т.к. DWORD выравняется по 4-байтовой границе.

    А в структуре SHELLSTATE применяется ещё и упаковка. По-умолчанию, BOOL занимает 4 байта, но в вашем случае:
    Код (C++):
      BOOL  fShowAllObjects  :1;
      BOOL  fShowExtensions  :1;
      BOOL  fNoConfirmRecycle  :1;
      BOOL  fShowSysFiles  :1;
      BOOL  fShowCompColor  :1;
      BOOL  fDoubleClickInWebView  :1;
      BOOL  fDesktopHTML  :1;
      BOOL  fWin95Classic  :1;
    Всё это занимает 8 бит (1 байт).

    Вот и считайте: на калькуляторе число 24 из 16-ричной переводите в 2-ичную, и смотрите какой бит, что означает.

    0х24 = 00100100 = (3-й бит + 6-й бит (счёт справа налево)) = fNoConfirmRecycle + fDoubleClickInWebView.

    Если я правильно понимаю, за это отвечает опция:
    Значит вам нужно работать с 6-м битом.

    2^6 = 32 (в десятичной СС).

    Добавляете к первому байту - активируется опция. (арифметическое ИЛИ)
    Отнимаете - деактивируется. (арифметическое "И" "НЕ")

    Вот на MS Technet писали точно такой VBS скрипт: https://social.technet.microsoft.co...-in-windows-explorer-registry?forum=w7itproui
    Только там операция XOR, а не OR. XOR - переключает бит. Если опция включена, то скрипт её отключит, и наоборот.
     
    Последнее редактирование: 24 ноя 2017
    DllPok и akok нравится это.
  6. Dragokas

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    5.341
    Симпатии:
    5.248
    Лучший ответ
    Вообщем, как выяснилось, в реестре размер структуры на 4 байта больше.
    Первые 4 байта - это размер самой структуры 0x24 = 36 байт. А вот всё остальное - это SHELLSTATE structure.

    Если всё расписать, то будет так:

    То, что у меня в реестре:

    24 00 00 00 3c 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 12 00 00 00 00 00 00 00 22 00 00 00

    0x24 (24 00 00 00) - размер структуры в реестре (36 байт)

    0x3с
    BOOL fShowAllObjects :1;
    BOOL fShowExtensions :1;
    BOOL fNoConfirmRecycle :1;
    BOOL fShowSysFiles :1;
    BOOL fShowCompColor :1;
    BOOL fDoubleClickInWebView :1;
    BOOL fDesktopHTML :1;
    BOOL fWin95Classic :1;

    0x28
    BOOL fDontPrettyPath :1;
    BOOL fShowAttribCol :1;
    BOOL fMapNetDrvBtn :1;
    BOOL fShowInfoTip :1;
    BOOL fHideIcons :1;
    BOOL fWebView :1;
    BOOL fFilter :1;
    BOOL fShowSuperHidden :1;

    0x00
    BOOL fNoNetCrawling :1;

    0x00
    выравнивание

    0x283c (3c 28 00 00)
    DWORD dwWin95Unused;
    0x00 (00 00 00 00)
    UINT uWin95Unused;
    0x00 (00 00 00 00)
    LONG lParamSort;
    0x01 (01 00 00 00)
    int iSortDirection;
    0x12 (12 00 00 00)
    UINT version;
    0x00 (00 00 00 00)
    UINT uNotUsed;

    0x22 (22 00)
    BOOL fSepProcess :1;
    BOOL fStartPanelOn :1;
    BOOL fShowStartPage :1;
    BOOL fAutoCheckSelect :1;
    BOOL fIconsOnly :1;
    BOOL fShowTypeOverlay :1;
    BOOL fShowStatusBar :1;
    UINT fSpareFlags :9;

    т.е. fSpareFlags << 7 и записывается сюда -> (22 00)

    00 00
    выравнивание до конца структуры.

    Учтите, что после изменений данных напрямую в реестре, не все настройки применяются автоматически.
    Например, двойной клик у меня меняется на одиночный сразу, а вот наоборот - нет. Нужна перезагрузка оболочки проводника.
    Так что потребуется ещё либо применять что-то вроде батника:
    Код (Text):

    taskkill /f /im explorer.exe
    explorer.exe
     
    (собственно в скрипте на technet так и сделали),
    либо всё гораздо проще реализуется на C++.
    Вот пример получения всех полей:
    Код (C++):
    #include <Shlobj.h>
    #include <windows.h>
    int main(int argc, char *argv[])
    {
        SHELLSTATE SS = {0};
        SHGetSetSettings(&SS, -1, 0);
    }
    Вот пример инвертирования бита:
    Код (C++):
    #include <Shlobj.h>
    #include <windows.h>

    int main(int argc, char *argv[])
    {
        SHELLSTATE SS = {0};
        SHGetSetSettings(&SS, SSF_DOUBLECLICKINWEBVIEW, false);

        SS.fDoubleClickInWebView ^= 1;

        SHGetSetSettings(&SS, SSF_DOUBLECLICKINWEBVIEW, true);
    }
    Перезагрузка оболочки не нужна.
     
    Последнее редактирование: 26 ноя 2017
    ScriptMakeR, bob_plus, akok и ещё 1-му нравится это.
  7. bob_plus

    bob_plus Новый пользователь

    Сообщения:
    12
    Симпатии:
    2
    Вы хорошо препарировали! Си в данном случае не интересует. На сколько пригодно для скрипта определюсь, как вернусь из поездки. Спасибо!
     
  8. bob_plus

    bob_plus Новый пользователь

    Сообщения:
    12
    Симпатии:
    2
    Чтобы переварить я еще раз сбросил этот ключ из нескольких сборок:
    windows 7 pro x64 (c i5)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,33,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,13,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    windows 7 pro x64 (c i7)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,33,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,33,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,13,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,33,00,00,00
    windows 7 max x64 (c i7)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,33,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,13,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    windows 7 pro x32 (c i7)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,33,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,33,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,13,a8,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,33,00,00,00
    windows 7 Se7en x32 (c i7)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,3c,a8,01,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,1c,a8,01,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00
    windows 10 corp x32 (vBox)
    Открывать двойным, а выделять одним щелчком:24,00,00,00,34,28,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,13,00,00,00,00,00,00,00,62,00,00,00
    Открывать двойным щелчком, а выделять
    указателем: 24,00,00,00,1c,28,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,13,00,00,00,00,00,00,00,62,00,00,00

    За реакцию подчеркивания ярлыка отвечает "IconUnderline"=dword:00000003, её значение: "всегда подчеркнуто" = 3, "подчеркивать при наведении" = 2.

    По структуре я меня сложились следующие представления:
    Она состоит из 4-байтных слов, длина которой описывается в первом слове: в данном случае - 24, что соответствует длине ShellState в 36 байт.
    Каждое слово в бинарной форме фактически является строкой флагов разного назначения: Boolean - это или "Да"(True)(1), или "Нет"(False)(0).
    Я положил Ваше описание (из MSDN) на трактовку назначений так чтобы строки читались "в одну строку" (извиняюсь за тавтологию) и поместил в спойлер:
    0x3с
    BOOL fShowAllObjects :1; TRUE для отображения всех объектов, включая скрытые файлы и папки. FALSE, чтобы скрыть скрытые файлы и папки.
    BOOL fShowExtensions :1; TRUE, чтобы показать расширения имен файлов, FALSE, чтобы скрыть их.
    BOOL fNoConfirmRecycle :1; TRUE, чтобы не отображать диалоговое окно подтверждения при удалении элементов в корзину, FALSE, чтобы отобразить диалоговое окно подтверждения.
    BOOL fShowSysFiles :1; TRUE, чтобы показать системные файлы, FALSE, чтобы скрыть их.
    BOOL fShowCompColor :1; TRUE для отображения зашифрованных или сжатых файлов NTFS в цвете.
    BOOL fDoubleClickInWebView :1; TRUE двойной клик, чтобы открыть элемент, когда он находится в веб-представлении.
    BOOL fDesktopHTML :1; TRUE для использования Active Desktop, в противном случае FALSE .
    BOOL fWin95Classic :1; TRUE для обеспечения соблюдения поведения и ограничений Windows 95 Shell.

    0x28
    BOOL fDontPrettyPath :1; TRUE, чтобы предотвратить преобразование пути ко всем строчным символам.
    BOOL fShowAttribCol :1; Не используется.
    BOOL fMapNetDrvBtn :1; TRUE для отображения кнопки сетевого сетевого диска.
    BOOL fShowInfoTip :1; TRUE, чтобы показать всплывающее описание для папок и файлов.
    BOOL fHideIcons :1; TRUE, чтобы скрыть значки на рабочем столе, FALSE, чтобы показать их.
    BOOL fWebView :1; TRUE для отображения в виде веб-представления.
    BOOL fFilter :1; Не используется.
    BOOL fShowSuperHidden :1; TRUE для отображения файлов операционной системы (системных файлов).

    0x00
    BOOL fNoNetCrawling :1; TRUE, чтобы отключить автоматический поиск сетевых папок и принтеров.

    0x00
    выравнивание

    0x283c (3c 28 00 00)
    DWORD dwWin95Unused; Не используется.
    0x00 (00 00 00 00)
    UINT uWin95Unused; Не используется.
    0x00 (00 00 00 00)
    LONG lParamSort; Колонка для сортировки.
    0x01 (01 00 00 00)
    int iSortDirection; Алфавитное направление сортировки для столбца, указанного lParamSort. Используйте 1 для восходящей сортировки, -1 для нисходящей сортировки.
    0x12 (12 00 00 00)
    UINT version; Не используется.
    0x00 (00 00 00 00)
    UINT uNotUsed; Не используется.

    0x22 (22 00)
    BOOL fSepProcess :1; TRUE для запуска окон папок в отдельных процессах, FALSE для запуска в том же процессе.
    BOOL fStartPanelOn :1; Только XP. TRUE - меню «Пуск» в стиле XP, FALSE - использовать классическое меню «Пуск».
    BOOL fShowStartPage :1; Не используется.
    BOOL fAutoCheckSelect :1; Представлен в Vista. TRUE - вид папки флажков в стиле Vista, FALSE - классические представления.
    BOOL fIconsOnly :1; Представлен в Vista. TRUE - показывать только общие значки, FALSE - отображения значков в стиле значков в папках.
    BOOL fShowTypeOverlay :1; Представлен в Vista. TRUE указывает, что в миниатюре должно отображаться приложение, которое будет вызываться при открытии элемента, FALSE указывает, что приложение не будет показано.
    BOOL fShowStatusBar :1; Представлен в Windows 8. TRUE для отображения строки состояния; для сокрытия FALSE.
    UINT fSpareFlags :9; Не используется.

    т.е. fSpareFlags >> 7 и записывается сюда -> (22 00)
    Под "выравниванием" видимо подорозумевается приведения какого-то слова к 4-байтной форме. Или я ошибаюсь?
    Мне остались непонятными Ваши высказывания на тему обратного прочтения, или это относилось преобразованию из 16-ричной формы в двоичную?
    Еще: эта часть между 0x283c (3c 28 00 00) и UINT uNotUsed. Если по MSDN она (почти) не используется, то как в нее попало слово с 3c 28 ?
    И как "fSpareFlags >> 7 и записывается сюда -> (22 00)", если MSDN говорит, что fSpareFlags :9; Не используется?
    К стати это последнее слово изменяется в разных сборках, и операционках (см. спойлер с Windows 10). Интересно, какую роль имеет это слово?..
    Моя "соображалка буксует". "Подсыпьте песочку"...:Acute:
     
    Последнее редактирование: 26 ноя 2017
  9. Dragokas

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    5.341
    Симпатии:
    5.248
    Нет.
    BOOL fShowAllObjects :1; - 1 бит (см. число после двоеточия).

    Эти по 4 байта:
    DWORD dwWin95Unused;
    UINT uWin95Unused;
    LONG lParamSort;
    int iSortDirection;
    UINT version;
    UINT uNotUsed;

    Да.
    Нет.
    Выражаясь в грубой форме, это нулевые байты, которые вставляются в структуру памяти, чтобы подравнять следующее (например, 4-байтовое слово) к началу 4-байтовой сетки.
    Например, вот вам структура:
    {
    BYTE b (1 байт)
    DWORD dw (4 байта)
    }
    Допустим:
    b = 0xFF;
    dw = 0x12345678;
    Вот вам произвольное состояние памяти с этой структурой:
    Код (Text):

    |FF000000|78563412|00000000|
    |00000000|00000000|00000000|
     
    dw не может размещаться в памяти сразу после FF, т.к. оказалось бы на пересечении границы сетки. Поэтому система добавила 3 байта на выравнивание.
    Также, минимально адресуемая единица объема памяти - 1 байт. Поэтому, если в структуре данные упакованы в 1 бит, то вы сперва объединяете биты в байт и после этого записываете в память (в вашем случае - в бинарном виде в реестр в 16-ричной СС).

    Байты записываются в память по адресу в обратном порядке (как в примере выше). В вашем случае, в реестр они записываются в таком же порядке, как и в память.

    Единственное, что в MSDN могут означать слова "Not used" или "Reserved" - это то, что данные поля недокументированны.
    Такое часто бывает, и в сети периодически появляются по некоторым функциям описания подобных полей, сделанные исследователями путём экспериментов и наблюдений.
    Бывает и такое, что Microsoft просто не торопится обновить документацию, при этом в соседних статьях от той же Майкрософт вдруг появляется упоминание какого-то неизвестного поля.

    Ну во-первых << 7 это смещение числа на 7 бит. И я там ошибся - сдвиг влево, а не вправо, так что я поправил в посте выше.
    Т.е. чтобы получить итоговый байт, вы объединяете вот эти 7 битов в байт:
    BOOL fSepProcess :1;
    BOOL fStartPanelOn :1;
    BOOL fShowStartPage :1;
    BOOL fAutoCheckSelect :1;
    BOOL fIconsOnly :1;
    BOOL fShowTypeOverlay :1;
    BOOL fShowStatusBar :1;
    Затем берёте число UINT fSpareFlags сдвигаете на 7 битов влево (на калькуляторе Windows это кнопка "RoL") (получаете 2-байтовое число) и складываете с получившимся байтом. Итог записываете в память, опять же в обратном порядке.
    Выше уже ответил.
    Но ведь 0x22 (16) == 100010 (2), а значит не относится к полю fSpareFlags, которое начинается с 8-го бита (если считать от единицы).
    100010 (2) == fStartPanelOn | fShowTypeOverlay

    Но если слишком сложно, может и не стоит так подробно разбираться? Пусть вам просто напишут скрипт.
     
    Последнее редактирование: 26 ноя 2017
    akok нравится это.
  10. bob_plus

    bob_plus Новый пользователь

    Сообщения:
    12
    Симпатии:
    2
    >Она состоит из 4-байтных слов, длина которой описывается в первом слове.
    >Нет.
    >BOOL fShowAllObjects :1; - 1 бит (см. число после двоеточия).
    В этот раз Вы меня не поняли. Я писал, что структура описывается 4-байтными словами, которые фактически являются 16-ричным представлением набора флагов, имеющих значение и размерность отраженные в описании.
    > ...на пересечении границы сетки...
    Ну так это и есть - приведение числа к байтовой размерности слов...
    >..."Not used" или "Reserved"...
    Я заметил, что в описании указано отношение сведений к версиям не младше w2k3.
    >Но если слишком сложно...
    Нет не сложно. Просто у каждого индивидуума есть своя лексика. Для одних она прекрасно подходит, другим - нет. Этим и отличаются преподаватели в ВУЗах.

    Утилитарные цели, для которых вся эта возня, ориентированы в первую очередь на приведение моих мозгов в былое состояние. Кроме того все, в чем Вы оказываете помощь, мне не удалось отрыть в Интернете. Может терпения не хватило: начинаю "задыхаться" уже в конце первой пятидесятки ссылок. Если бы я обнаружил такое подобие препарирования, как здесь - не было бы нужды затевать это снова. Может "масла в башке" не хватило на правильный запрос..:Fool:
     
  11. Dragokas

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    5.341
    Симпатии:
    5.248
    В вашем случае: 1, 2 и 4 байтовыми.
    Число ни к чему не приводится. Меняется только его расположение в структуре памяти.
    Приведу пример по уже знакомым вам цифрам:
    Код (C++):
    {
        BYTE b;
        DWORD dw;
    }
    Код (Text):

    |FF000000|78563412|00000000|
     
    Если бы мы преобразовали тип данных BYTE -> DWORD и получили бы число 0xFF типа DWORD, то в памяти оно бы записалось вот так:
    Код (Text):

    |000000FF|78563412|00000000|
     
    Число 0x12345678 осталось на месте, дополнительного выравнивания не потребовалось, а вот число 0xFF записалось в неверную позицию. И теперь если система будет считывать с памяти по адресу начала структуры тип BYTE, она прочитает 0x00 вместо 0xFF.
    Кстати, выравнивание не всегда будет = 4 байтам, это зависит от размера типа данных поля.
    Чтобы понять как это устроено, можете ещё почитать эту заметку: http://www.cyberforum.ru/win-api/thread1982664.html#post10444442
    Я там сам задавал вопросы, посколько также не так давно изучал эту тему. Там же справшивал и про битовые поля, т.к. сам почти первый раз сталкиваюсь с этим.
    Если в описании параметра или в Remarks указаны ограничения к версиям ОС, то обычно оно так и есть.
    Но размеры структуры это не меняет. Если это влияет на размеры структуры, то так и должно быть указано в виде условного форматирования в полях самой структуры, например, см. LVITEM.
     
    Кирилл и akok нравится это.

Поделиться этой страницей

Загрузка...