Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > CodeGuard и выравнивание.


Автор: Riply 15.7.2008, 00:20
Здравствуйте !
Не могу определить область в которой у меня "недопонимание" (С,  Builder или Native, а  может и все вместе smile. 
Решила, что поместив в "для новичков" точно не ошибусь smile
Имеем C++ Builder и следующую процедуру:
Код

NTSTATUS TLockFileNt::_DirectCreateFile
            (const PUNICODE_STRING pObjName, const ACCESS_MASK DesAccess, const PIO_STATUS_BLOCK pIoBlock, const ULONG FileAttr,
             const ULONG ShareAccess, const ULONG CreateDispos, const ULONG CreateOptions, const PHANDLE pRootDir)
{
  OBJECT_ATTRIBUTES ObjAttr;
  if (pRootDir)
    InitializeObjectAttributes(&ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, *pRootDir, NULL);
    else InitializeObjectAttributes(&ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, 0, NULL);
  assert(((ULONG)(&ObjAttr) & PRED_32) == 0);
  assert(((ULONG)(pObjName) & PRED_32) == 0);
  NTSTATUS RetStatus = NtCreateFile(&FFileHandle, DesAccess, &ObjAttr, pIoBlock, NULL,
                          FileAttr, ShareAccess, CreateDispos, CreateOptions, NULL, 0);
  if (! NT_SUCCESS(RetStatus)) FFileHandle = 0;
  return RetStatus;
};

Все работает, пока мы не меняем настройки CodeGuard
После включения опции "All CodeGuard options on"
NtCreateFile выдает STATUS_DATATYPE_MISALIGNMENT (Invalid access to memory location)
Nt - описание:
// Alignment Fault
// A datatype misalignment was detected in a load or store instruction.
//...winnt #define STATUS_DATATYPE_MISALIGNMENT     ((NTSTATUS)0x80000002L)

Насколько я понимаю, требуется выравнивание на 32 битную границу.
Но assert`ы не срабатывают. Значит передаем, вроде правильно...

Соответственно, появляются два вопроса:
Почему так происходит ?
Как с этим бороться ? (Отключение CodeGuard`а считаю недостойным решением smile

Автор: ama_kid 15.7.2008, 07:14
попробуй поиграться параметрами Data Aligment на вкладке "Advanced compile". Билдера под рукой нет, проверить не могу, но есть ощущение, что структуру OBJECT_ATTRIBUTES надо выравнивать как-то...  smile 

Автор: Riply 15.7.2008, 08:06
Цитата(ama_kid @  15.7.2008,  07:14 Найти цитируемый пост)
попробуй поиграться параметрами Data Aligment на вкладке "Advanced compile". 


Ух ты, какая полезная "вкладка" smile
Но она не помогла  smile 
Я еще пока плаваю во всяких директивах компилятору.
Может быть такое, что с ними я напартачила в одном юните, а аукается это в другом ?

Автор: jonie 15.7.2008, 19:32
еще билдер вроде как поддерживает директиву #pragma
Код
#pragma pack(push)
#pragma pack(1)
typedef struct{...}blablabla;
#pragma pack(pop)

Автор: Riply 16.7.2008, 02:22
Докопалась до вот этого:
В одном из юнитов (не в том где вызывается наша процедура) есть такие строчки:
Код

#define RTL_CONSTANT_STRING(s)  { sizeof(s)-sizeof((s)[0]), sizeof(s), s }

const UNICODE_STRING NtDll_LibNameU = RTL_CONSTANT_STRING(L"ntdll.dll");


Если их закоментировать, то проекту становиться глубоко чихать на настройки CodeGuard.
Знай себе работает и не пискает smile
Если же их "открыть", то работаем только с отключенным CodeGuard (ошибка описана выше).

Объясните, пожалуйста, что крамольного в таком объявлении
и как эта крамола влияет на работу ?

Автор: bsa 16.7.2008, 11:30
Riply, ну если представить себя препроцессором и обработать эти строчки, то получится, что переменной NtDll_LibNameU присваивается набор значений, в частности, два числа и указатель на строку. А так как объявления UNICODE_STRING нет, то нельзя сделать вывод, что это за структура такая...

Автор: ama_kid 16.7.2008, 13:11
Цитата(bsa @  16.7.2008,  11:30 Найти цитируемый пост)
А так как объявления UNICODE_STRING нет, то нельзя сделать вывод, что это за структура такая... 
В принципе, это штатная DDK-шная структура для работы с юникодными функциями
Код
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;
Другое дело, что сложно представить где объявление, используемое даже для написания драйверов kernel-mode, может аукнуться в обычном приложении.  smile
Цитата(Riply @  16.7.2008,  02:22 Найти цитируемый пост)
Объясните, пожалуйста, что крамольного в таком объявлении
и как эта крамола влияет на работу ?
Как влияет - ты уже выснила smile Крамольного, в принципе, ничего не вижу, но к примеру, где-нить может стоять директива типа такой:
Код
#ifdef RTL_CONSTANT_STRING 
...
#else
...
#endif
в которой CodeGuard в зависимости от этой декларации использует разные вызовы... Ввиду того, что неизвестно, какие хедеры\либы ты в своем проекте подключала, а самому сымитировать проблему не получилось, предположить что-либо более правдоподобное сложно smile

Автор: Riply 16.7.2008, 13:45
Цитата(ama_kid @  16.7.2008,  13:11 Найти цитируемый пост)
Ввиду того, что неизвестно, какие хедеры\либы ты в своем проекте подключала, а самому сымитировать проблему не получилось, предположить что-либо более правдоподобное сложно 


"сымитировать проблему" очень просто.
Прежде чем утверждать, что влияют именно эти строчки, я попробовала исключить 
все возможные собственные ляпы следующим образом:
1. Создала новый пустой проект (WindowsFormApplication) C++Builder 2006
2. Нашла и скопировала в него код из http://forum.vingrad.ru/index.php?showtopic=180900&view=findpost&p=1310202
    (некоторым он должен быть очень знаком  smile )
3. Добавила туда #include <winternl.h> и эти две строчки
4. Включила CodeGuard + в Tools->CodeGuard Configuration включила Append to log file

Вот и все: наблюдаю этот эффект  smile 

Цитата(ama_kid @  16.7.2008,  13:11 Найти цитируемый пост)
где-нить может стоять директива типа такой:

Это некузявый вариант. Хорошо что данная вещь проявилась с помощью CodeGuard.
Где гарантии, что она не аукнется в другое время и в другом месте ?
Ведь истинные причины и механизм сбоя я до сих пор понять не сумела  smile

Добавлено через 8 минут и 22 секунды
Цитата(bsa @  16.7.2008,  11:30 Найти цитируемый пост)
Riply, ну если представить себя препроцессором


Попробовала (хотя мне ой как далеко до него  smile )
и с удивлением обнаружила, что ULONG(NtDll_LibNameU.Buffer) выражается аж нечетным числом.
Сейчас пытаюсь понять: это я ничего не смыслю в указателях из С или данный дефайн,
действительно никуда не годится smile

Автор: bsa 16.7.2008, 16:13
Riply, то, что buffer выражается нечетным числом, это не криминал. Это же указатель.

Автор: Riply 16.7.2008, 18:32
Цитата(bsa @  16.7.2008,  16:13 Найти цитируемый пост)
Riply, то, что buffer выражается нечетным числом, это не криминал. Это же указатель. 



"Как прикажешь тебя понимать, Саид ?" (с)
Насколько, я понимаю, криминал да еще и какой smile
Во всяком случае, ни одна из тех Nt-функций, на которых я проверяла, 
не переваривала "нечетный" Buffer в имени. (Хотя для забраковки метода достаточно, чтобы ругалась всего одна)
Впрочем, это легко проверить, инициализировав UNICODE_STRING вручную и передав в любую понравившуюся Nt-ф-ию.
Меня удивляет другое: то что мы получаем такой буфер этим "дефайном" и его влияние на "код в целом".


Автор: Riply 16.7.2008, 19:30
Может кому интересно. Вот маленький отчет:
Наш дефайн не виновен и полностью оправдан.
Тяжким бременем обвинения ложатся либо на Builder, либо на CodeGuard   smile 
Опыты показали следующее:
Код

UNICODE_STRING TestFile;// = RTL_CONSTANT_STRING(L"\\??\\E:\\Delete Files\\TestFile.txt");
RtlInitUnicodeString(&TestFile, L"\\??\\E:\\Delete Files\\TestLogFile.txt");

Данный вариант работает при любых настройках CodeGuard.
Но стоит раскоментировать первую строчку (не трогая вторую), и при включенном CodeGuard 
получаем "нечетный" Buffer и нецензурщину от NtCreateFile.
Причем не важно используем ли мы RTL_CONSTANT_STRING или расписываем его на месте вручную.
Эффект тот же. Т.е. данный способ декларации так влияет на инициализацию TestFile,
что не спасает даже последующая попытка использовать RtlInitUnicodeString.

P.S. Понимаю, что меня сейчас растерзают на месте, но скажу: Delphi себе таких шуток не позволяет smile

Автор: bsa 16.7.2008, 21:29
Riply, повторяю, нечетный указатель это не криминал.
Если хочешь проверить, сделай:
Код
char *buffer = new char[100];
char *p = buffer + 1;
Или buffer будет нечетным или p. И от этого ты никуда не денешься.

Автор: Riply 17.7.2008, 02:34
Цитата(bsa @  16.7.2008,  21:29 Найти цитируемый пост)
Riply, повторяю, нечетный указатель это не криминал.

Sorry, это я плохо излагаю свои мысли.
Я имела ввиду, что такая инициализация нашего Buffer`а, это криминал, как минимум, 
для нашего конкретного случая (аккуратно выражаясь), 
а скорее всего, это криминал для любой Nt-функции, принимающей на входе UNICODE_STRING.

Цитата(bsa @  16.7.2008,  21:29 Найти цитируемый пост)
Или buffer будет нечетным или p. И от этого ты никуда не денешься. 

Вот осторожность этой фразы меня и удивляет.
Ибо (при данном коде) я бы утверждала, что p будет нечетным, а buffer бутед выровнен на 32-битную границу,
а под BDS 2006 и выше на 64-битную. (Извращенные настройки среды мы не рассматриваем  smile )

Автор: bsa 17.7.2008, 21:10
Цитата(Riply @ 17.7.2008,  02:34)
Вот осторожность этой фразы меня и удивляет.

я стараюсь быть осторожным  smile 

Автор: Riply 18.7.2008, 02:37
Цитата(bsa @  17.7.2008,  21:10 Найти цитируемый пост)
я стараюсь быть осторожным  


Слава богу ! А то я уж испугалась, что данный код может возвращать "неровный" указатель smile

Ну вот. После того, как мы выяснили с какими неприятностями мы можем столкнутся,
встает несколько вопросов:
Как объявлять константы типа UNICODE_STRING, чтобы
 они сами были выровнены как минимум на 32-х битную границу
 и чтобы Buffer был выровнен как минимум на 32-х битную границу.
 Причем, чтобы это не зависило от внешних факторов (типа включения/выключения CodeGuard)
 и не влияло не остальной код ?

Второй вопрос:
есть у меня некая струтура. Код привожу на Delphi, ибо изясняясь только на этом языке (пока еще)
я могу быть уверена, что сказала именно то, что хотела сказать smile
Код

type
 PNamedGUID = ^TNamedGUID;
 TNamedGUID = packed record
  _Guid: TGUID;
  NameU: UNICODE_STRING;
 end;

const
_DiskDrive = 'DiskDrive'; // DiskDrive
 SysClassGuid_DiskDrive: TNamedGUID =
    (_Guid: '{4d36e967-e325-11ce-bfc1-08002be10318}';
     NameU: (Length: Length(_DiskDrive) shl SHR_WCHAR; 
            MaximumLength: Length(_DiskDrive) shl SHR_WCHAR + SizeOf(WideChar); Buffer: _DiskDrive));

Констант типа SysClassGuid_DiskDrive у меня как собак нерезанных smile
Как, соблюдая условия, описанные для UNICODE_STRING, инициализировать их ?
Причем сам _Guid должен быть выровнен как минимум на 64-х битную границу.
И можно ли инициализировать константу GUID строкой, как в Delphi
или мне вручную придется переводить строки типа '{4d36e967-e325-11ce-bfc1-08002be10318}'
в числовые значения ?

P.S. 
 Я не стала выносить вопрос по инициализаци чистого GUID в отдельную ветку, т.к.
 он неразрывно связан с выравниванием.


Автор: bsa 18.7.2008, 11:28
Если ты пишешь на билдере, то, думаю, там есть много функций одноименных аналогов дельфийских.

Автор: Riply 18.7.2008, 11:50
Цитата(bsa @  18.7.2008,  11:28 Найти цитируемый пост)
Если ты пишешь на билдере, то, думаю, там есть много функций одноименных аналогов дельфийских


В том то и дело, что я еще настолько начинающая, что даже не определилась на чем писать smile
Делаю так: пишу под Builder`ом, компилирую, проверяю корректность работы.
Перехожу на VS 2005, компилирую тот же юнит, проверяю корректность работы.
Если и там и там все в порядке, откладываю данный юнит как готовый у употреблению smile
Поэтому привязки к Builder`ским ф-иям мне, к сожалению, не подходят

Автор: W4FhLF 18.7.2008, 12:23
Системный софт для Windows лучше писать в средах от MS или по-крайней мере юзать хедеры и компилятор от MS. 

Автор: Riply 18.7.2008, 12:52
Цитата(W4FhLF @  18.7.2008,  12:23 Найти цитируемый пост)
Системный софт для Windows лучше писать в средах от MS или по-крайней мере юзать хедеры и компилятор от MS.


До написания "системного софта" мне как до луны smile
На данном этапе я учусь ствить "{" вместо "begin" smile
Заодно пытаюсь нучиться правильно декларировать констаны, структуры и т.д. и т.п., 
ну и, разумеется, работать с ними.

Как я поняла "сред от MS" много ?  Какую из них лучше выбрать для изучения "с нуля" ?
И где можо посмотреть(скачать) "хедеры от MS" ?

Автор: W4FhLF 18.7.2008, 13:05
Цитата(Riply @  18.7.2008,  12:52 Найти цитируемый пост)
Как я поняла "сред от MS" много ?  Какую из них лучше выбрать для изучения "с нуля" ?


Де-факто одна smile 

Цитата(Riply @  18.7.2008,  12:52 Найти цитируемый пост)
И где можо посмотреть(скачать) "хедеры от MS" ?


Если юзаешь студию 8-9, то для системного программирования там все зедеры есть. Для программирования дров надо качать спец. пакет WinDDK (бесплатно с сайта MS). Плюс сразу скачивай пакет Debuging Tools и символы(pdb). 

За подробностями сюда:

http://www.microsoft.com/whdc/devtools/default.mspx

+ желательно иметь исходники винды, стянуть откуда-нибудь из торрентов, иногда туда полезно заглядывать. 

Автор: Riply 18.7.2008, 13:15
Цитата(W4FhLF @  18.7.2008,  13:05 Найти цитируемый пост)
Если юзаешь студию 8-9 


Сейчас, у меня стоит VS 2005.
Скачала 2008 с http://www.microsoft.com/express/download,
но еще не ставила. Это то что нужно ?

quote=W4FhLF, 18.7.2008,  13:05, post1584084]За подробностями сюда:[/quote]

Спасибо.

Цитата(W4FhLF @  18.7.2008,  13:05 Найти цитируемый пост)
желательно иметь исходники винды, стянуть откуда-нибудь из торрентов, иногда туда полезно заглядывать


Ну в том, что полезно заглядывать в исходники, меня убеждать не надо smile
Правда, до этого, я лазила только в ReactOS. Есть что-то более близкое к оригиналу ?



[

Автор: W4FhLF 18.7.2008, 13:36
Цитата(Riply @  18.7.2008,  13:15 Найти цитируемый пост)
Это то что нужно ?


Если собираешься писать для висты включительно, то 2008 предпочтительнее просто из-за более новых хедеров и либ. 


Цитата(Riply @  18.7.2008,  13:15 Найти цитируемый пост)
Правда, до этого, я лазила только в ReactOS. Есть что-то более близкое к оригиналу ?


Ну я имел ввиду исходники Win NT4 и w2k, которые уплыли в сеть smile Хотя, там чёрт ногу сломит, иногда IDA + symbols помогают больше. Ну а если говорить о нормальной платформе для отладки дров, то тут лучше поставить VM и туда несколько ОС, держать для них символы и производить отладку удалённо через WinDBG (http://silverstr.ufies.org/lotr0/windbg-vmware.html), если будешь отлаживать свои дрова, то фактически отладка ничем не будет отличаться от гуляния по исходнику как в студии. 

Автор: Riply 18.7.2008, 15:35
W4FhLF, спасибо.

А с объявлением константы GUID, как я поняла, мне придется вручную
переводить строку в числовые значения ? 
Перевести то не сложно, но теряется "наглядность" да и в MSDN GUID "описывается" строками.

Автор: W4FhLF 18.7.2008, 15:53
Цитата(Riply @  18.7.2008,  15:35 Найти цитируемый пост)
А с объявлением константы GUID, как я поняла, мне придется вручнуюпереводить строку в числовые значения ? 


Функция http://msdn.microsoft.com/en-us/library/ms680589(VS.85).aspx сделает то, что тебе надо. Работает с т.н. OLESTR, которая по-существу является обычной Unicode строкой, поэтому передавай на вход UNICODE_STRING.Buffer.

Про функции для работы с UNICODE_STRING читать либо в MSDN, либо DDK Help, либо http://www.osronline.com/DDKx/kmarch/k112_401e.htm.

Автор: Riply 18.7.2008, 16:34
Цитата(W4FhLF @  18.7.2008,  15:53 Найти цитируемый пост)
Про функции для работы с UNICODE_STRING читать либо в MSDN, либо DDK Help, либо здесь. 


Да эти ф-ии я знаю.  
Мне нужно декларировать константу. Что-то типа:
const GUID MyGuid = {0, 1, 2, { 0, 1,  2,  3,  4,  5,  6,  7} };
Только хотелось вместо чисел использовать строку. В Delphi это возможно.
Вот я и интересовалась, реализовано ли это в C ?

Автор: W4FhLF 18.7.2008, 16:59
Цитата(Riply @  18.7.2008,  16:34 Найти цитируемый пост)
Только хотелось вместо чисел использовать строку. В Delphi это возможно.Вот я и интересовалась, реализовано ли это в C ?


Только если написать свой макрос, но я бы не стал заморачиваться. 

Автор: bsa 18.7.2008, 17:07
Цитата(Riply @ 18.7.2008,  16:34)
Вот я и интересовалась, реализовано ли это в C ?

Угу. Вот оно:
Код
#define RTL_CONSTANT_STRING(s)  { sizeof(s)-sizeof((s)[0]), sizeof(s), s }

Автор: W4FhLF 18.7.2008, 17:11
bsa, ты ничего не путаешь?

Цитата(http://msdn.microsoft.com/en-us/library/aa906838.aspx)

RTL_CONSTANT_STRING

The RTL_CONSTANT_STRING macro creates a string or Unicode string structure to hold a counted string.


Как это поможет из этого:

Цитата

"{4d36e967-e325-11ce-bfc1-08002be10318}"


Получить структуру:

Код

typedef struct _GUID {  
  DWORD Data1;  
  WORD Data2;  
  WORD Data3;  
  BYTE Data4[8];
} GUID;


Автор: Riply 18.7.2008, 17:30
Цитата(W4FhLF @  18.7.2008,  16:59 Найти цитируемый пост)
Только если написать свой макрос, но я бы не стал заморачиваться. 


Ну... "На нет и суда нет" smile
Насчет "заморачиваться" подумаю.
Этих констант много, лопатить их вручную лень.  Опять же потеря наглядности и "совместимости" с MSDN.
Есть еще один аргумент в пользу написания своего макроса: это поможет мне в обучении, если, конечно, получится smile

Автор: bsa 18.7.2008, 17:32
вообще-то я показал, как именно подобное замутить на Си.
Естественно, что реализация для GUID'а будет куда сложней. Хотя, если есть возможность отказаться от кавычек и дефисов, то можно вообще легко сделать. Если же нельзя, то придется огромный огород городить.

Автор: Riply 18.7.2008, 17:37
Цитата(bsa @  18.7.2008,  17:32 Найти цитируемый пост)
Естественно, что реализация для GUID'а будет куда сложней. Хотя, если есть возможность отказаться от кавычек и дефисов, то можно вообще легко сделать.


Я согласная (в смысле отказаться от "отказаться от кавычек" и уж если так необходимо, то и от дефисов). smile
Но, не вижу как "можно вообще легко сделать" (пока). 
Натолкните на путь истинный smile

Автор: bsa 18.7.2008, 19:07
Как-то так (я с ## не очень работал, поэтому мог перепутать):
Код
#define GUID_INIT(d0,d1,d2,d3,d4,d5) {0x##d1, 0x##d2, 0x##d3, {0x##d4 >> 8, 0x##d4 & 0xFF, 0x##d5 >> 40, (0x##d5>>32) & 0xFF, (0x##d5>>24) & 0xFF, ...}}

guid = GUID_INIT(4d36e967,e325,11ce,bfc1,08002be10318);

Автор: Riply 19.7.2008, 07:43
Цитата(bsa @  18.7.2008,  19:07 Найти цитируемый пост)
код C++


Спасибо. 
Не ожидала, что в C могут "проскакивать" подобные вещи smile (Delphi такие фокусы и не снились smile)
Правда у меня среда ругается, говорит мол [C++ Warning] Main.cpp(122): W8056 Integer arithmetic overflow
и так как я еще не разобралась, почему она не хочет так работать с Int64, решила попробовать
сделать чуть по-другому. Вот что вышло:
Первую ф-ию  (RtlGUIDFromStringROs) я нагло сперла у ReactOS-евцев, 
чтобы наш "дефайн" не был "завязан" на NtDll (или на что-нибудь другое smile)

Код

NTSTATUS NTAPI RtlGUIDFromStringROs(const PUNICODE_STRING pUs, OUT GUID* pGd)
{
        int i = 0;
        const WCHAR *lpszCLSID = pUs->Buffer;
        BYTE* lpOut = (BYTE*)pGd;
        // Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
        // to memory:       DWORD... WORD WORD BYTES............
            while (i <= 37)
            {
                    switch (i)
                        {
                                case 0:
                                    if (*lpszCLSID != '{') return STATUS_INVALID_PARAMETER;
                                    break;
                                case 9:
                                case 14:
                                case 19:
                                case 24:
                                    if (*lpszCLSID != '-') return STATUS_INVALID_PARAMETER;
                                    break;
                                case 37:
                                    if (*lpszCLSID != '}') return STATUS_INVALID_PARAMETER;
                                    break;
                                default:
                                    {
                                            WCHAR ch = *lpszCLSID, ch2 = lpszCLSID[1];
                                            unsigned char byte;
                                            // Read two hex digits as a byte value
                                            if (ch >= '0' && ch <= '9') ch = ch - '0'; else
                                                if (ch >= 'a' && ch <= 'f') ch = ch - 'a' + 10; else
                                                    if (ch >= 'A' && ch <= 'F') ch = ch - 'A' + 10; else return STATUS_INVALID_PARAMETER;

                                            if (ch2 >= '0' && ch2 <= '9') ch2 = ch2 - '0'; else
                                                if (ch2 >= 'a' && ch2 <= 'f') ch2 = ch2 - 'a' + 10; else
                                                    if (ch2 >= 'A' && ch2 <= 'F') ch2 = ch2 - 'A' + 10; else return STATUS_INVALID_PARAMETER;

                                            byte = ch << 4 | ch2;

                                            switch (i)
                                                            {
#ifndef WORDS_BIGENDIAN
    // For Big Endian machines, we store the data such that the
    // dword/word members can be read as DWORDS and WORDS correctly.
                                                                    // DWord
                                                                    case 1:
                                                                        lpOut[3] = byte;
                                                                        break;
                                                                    case 3:
                                                                        lpOut[2] = byte;
                                                                        break;
                                                                    case 5:
                                                                        lpOut[1] = byte;
                                                                        break;
                                                                    case 7:
                                                                        lpOut[0] = byte;
                                                                        lpOut += 4;
                                                                        break;
                                                                    // Word
                                                                    case 10:
                                                                        case 15:
                                                                            lpOut[1] = byte;
                                                                            break;
                                                                        case 12:
                                                                        case 17:
                                                                            lpOut[0] = byte;
                                                                            lpOut += 2;
                                                                            break;
#endif
                                                                    // Byte
                                                                    default:
                                                                        lpOut[0] = byte;
                                                                        lpOut++;
                                                                        break;
                                                            }
                                                            lpszCLSID++; /* Skip 2nd character of byte */
                                                            i++;
                                    }
                        }
                lpszCLSID++;
                i++;
            }
    return STATUS_SUCCESS;
};

GUID RtlGUIDFromUnicodeStringROs(const PUNICODE_STRING pUs)
{
        GUID Gd;
        if ((!pUs) || (RtlGUIDFromStringROs(pUs, &Gd) != STATUS_SUCCESS)) ZeroMemory_128(&Gd);
        return Gd;
};

GUID __GUIDFromWChar(wchar_t * pBuffer, ULONG cbBuffer)
{
        UNICODE_STRING Us = { cbBuffer - sizeof(WCHAR), cbBuffer, pBuffer };
        return RtlGUIDFromUnicodeStringROs(&Us);
};


Ну вот. Подготовка завершена, теперь попробуем определить наш "дефайн"
и проверить его работоспособность:

Код

#define GUID_INIT_REACTOS(_ws) ( __GUIDFromWChar( (wchar_t * )(_ws), sizeof(_ws)) )

const GUID GuidReactOs = GUID_INIT_REACTOS(L"{4d36e967-e325-11ce-bfc1-08002be10318}");


void __fastcall TMainForm::btnFirstTestClick(TObject *Sender)
{
        GUID GuidNt;
        UNICODE_STRING Us = RTL_CONSTANT_STRING(L"{4d36e967-e325-11ce-bfc1-08002be10318}");
        if (NT_SUCCESS(RtlGUIDFromString(&Us, &GuidNt)))
            if (IsEqualGUID(GuidNt, GuidReactOs)) ShowMessage("Guid are equal");
}


Вроде получилось smile
Буду очень признательна, за тыканье меня носом в ошибки, неувязки или просто в "так не делают" smile

Автор: Riply 21.7.2008, 06:20
Если кому интересно:
По первым тестам, данному "дефайну"
Код

#define DECLARE_RTL_UNICODE_STRING_CONSTANT(d, s) \
    DECLSPEC_ALIGN(32) const WCHAR d##_value[sizeof(s)/sizeof(WCHAR)] = { s }; \
    const UNICODE_STRING d = \
            {sizeof(s)-sizeof((s)[0]), sizeof(s), const_cast<WCHAR*>(d##_value) };

глубоко плевать на всякие там CodeGuard`ы вместе с их опциями - знай себе выдает "правильный" Buffer smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)