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

bob_plus

Новый пользователь
Сообщения
12
Реакции
2
Баллы
13
Попробовал порулить по мелочи (сделать переключение "открывать одним кликом" из скрипта ) параметром 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

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

И как он вообще формируется?
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,141
Реакции
5,913
Баллы
648
Здравствуйте, bob_plus !

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

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

bob_plus

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

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,141
Реакции
5,913
Баллы
648
Если не сложно: что такое "выравнивание"? По отношению к чему? Про двоеточие - то из справки MSDN?
Выравнивание по отношению к границе, в данном случае 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.

открывать одним кликом
Если я правильно понимаю, за это отвечает опция:
MSDN написал(а):
fDoubleClickInWebView

Type: BOOL

TRUE to require a double-click to open an item when in web view.
Значит вам нужно работать с 6-м битом.

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

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

Вот на MS Technet писали точно такой VBS скрипт: https://social.technet.microsoft.com/Forums/windows/en-US/cc220a3d-1a68-441e-9dc0-a5d4714bccdd/singleclick-to-open-in-windows-explorer-registry?forum=w7itproui
Только там операция XOR, а не OR. XOR - переключает бит. Если опция включена, то скрипт её отключит, и наоборот.
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,141
Реакции
5,913
Баллы
648
Вообщем, как выяснилось, в реестре размер структуры на 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
выравнивание до конца структуры.

Учтите, что после изменений данных напрямую в реестре, не все настройки применяются автоматически.
Например, двойной клик у меня меняется на одиночный сразу, а вот наоборот - нет. Нужна перезагрузка оболочки проводника.
Так что потребуется ещё либо применять что-то вроде батника:
Код:
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);
}
Перезагрузка оболочки не нужна.
 
Последнее редактирование:

bob_plus

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

bob_plus

Новый пользователь
Сообщения
12
Реакции
2
Баллы
13
Чтобы переварить я еще раз сбросил этот ключ из нескольких сборок:
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:
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,141
Реакции
5,913
Баллы
648
Она состоит из 4-байтных слов, длина которой описывается в первом слове
Нет.
BOOL fShowAllObjects :1; - 1 бит (см. число после двоеточия).

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

Boolean - это или "Да"(True)(1), или "Нет"(False)(0).
Да.
Под "выравниванием" видимо подорозумевается приведения какого-то слова к 4-байтной форме. Или я ошибаюсь?
Нет.
Выражаясь в грубой форме, это нулевые байты, которые вставляются в структуру памяти, чтобы подравнять следующее (например, 4-байтовое слово) к началу 4-байтовой сетки.
Например, вот вам структура:
{
BYTE b (1 байт)
DWORD dw (4 байта)
}
Допустим:
b = 0xFF;
dw = 0x12345678;
Вот вам произвольное состояние памяти с этой структурой:
Код:
|FF000000|78563412|00000000|
|00000000|00000000|00000000|
dw не может размещаться в памяти сразу после FF, т.к. оказалось бы на пересечении границы сетки. Поэтому система добавила 3 байта на выравнивание.
Также, минимально адресуемая единица объема памяти - 1 байт. Поэтому, если в структуре данные упакованы в 1 бит, то вы сперва объединяете биты в байт и после этого записываете в память (в вашем случае - в бинарном виде в реестр в 16-ричной СС).

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

Еще: эта часть между 0x283c (3c 28 00 00) и UINT uNotUsed. Если по MSDN она (почти) не используется, то как в нее попало слово с 3c 28 ?
Единственное, что в MSDN могут означать слова "Not used" или "Reserved" - это то, что данные поля недокументированны.
Такое часто бывает, и в сети периодически появляются по некоторым функциям описания подобных полей, сделанные исследователями путём экспериментов и наблюдений.
Бывает и такое, что Microsoft просто не торопится обновить документацию, при этом в соседних статьях от той же Майкрософт вдруг появляется упоминание какого-то неизвестного поля.

И как "fSpareFlags >> 7 и записывается сюда -> (22 00)", если MSDN говорит, что fSpareFlags :9; Не используется?
Ну во-первых << 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-байтовое число) и складываете с получившимся байтом. Итог записываете в память, опять же в обратном порядке.
если MSDN говорит, что fSpareFlags :9; Не используется?
Выше уже ответил.
Но ведь 0x22 (16) == 100010 (2), а значит не относится к полю fSpareFlags, которое начинается с 8-го бита (если считать от единицы).
100010 (2) == fStartPanelOn | fShowTypeOverlay

Моя "соображалка буксует". "Подсыпьте песочку"...:Acute:
Но если слишком сложно, может и не стоит так подробно разбираться? Пусть вам просто напишут скрипт.
 
Последнее редактирование:
  • Like
Реакции: akok

bob_plus

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

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

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,141
Реакции
5,913
Баллы
648
Я писал, что структура описывается 4-байтными словами
В вашем случае: 1, 2 и 4 байтовыми.
Ну так это и есть - приведение числа к байтовой размерности слов...
Число ни к чему не приводится. Меняется только его расположение в структуре памяти.
Приведу пример по уже знакомым вам цифрам:
C++:
{
    BYTE b;
    DWORD dw;
}
Код:
|FF000000|78563412|00000000|
Если бы мы преобразовали тип данных BYTE -> DWORD и получили бы число 0xFF типа DWORD, то в памяти оно бы записалось вот так:
Код:
|000000FF|78563412|00000000|
Число 0x12345678 осталось на месте, дополнительного выравнивания не потребовалось, а вот число 0xFF записалось в неверную позицию. И теперь если система будет считывать с памяти по адресу начала структуры тип BYTE, она прочитает 0x00 вместо 0xFF.
Кстати, выравнивание не всегда будет = 4 байтам, это зависит от размера типа данных поля.
Чтобы понять как это устроено, можете ещё почитать эту заметку: http://www.cyberforum.ru/win-api/thread1982664.html#post10444442
Я там сам задавал вопросы, посколько также не так давно изучал эту тему. Там же справшивал и про битовые поля, т.к. сам почти первый раз сталкиваюсь с этим.
Я заметил, что в описании указано отношение сведений к версиям не младше w2k3.
Если в описании параметра или в Remarks указаны ограничения к версиям ОС, то обычно оно так и есть.
Но размеры структуры это не меняет. Если это влияет на размеры структуры, то так и должно быть указано в виде условного форматирования в полях самой структуры, например, см. LVITEM.
 
Сверху Снизу