Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Вниз

Запуск команды runas   Найти похожие ветки 

 
olevacho ©   (2004-10-30 15:56) [0]

Есть в винде ХР команда runas. Она позволяет находясь в системе под одним пользователем  выполнить другую команду или внешнюю программу от имени другого пользователя. Проблемма в том что нужно после запуска вводить пароль другого пользователя вручную. Можно ли сделать прогу на дельфе так чтоб пароль другого пользователя передавался из моей проге команде runas автоматически. А может в дельфе есть какой-нить аналог команды runas ?


 
GuAV ©   (2004-10-30 16:10) [1]

CreateProcessAsUser

В MSDN есть пример, как раз то счто нужно, только перевести на Delphi.


 
Игорь Шевченко ©   (2004-10-30 17:10) [2]

CreateProcessWithLogonW

procedure TfMain.MyCreateProcess;
const
 UserName : WideString = "TESTUSER";
 Password : WideString = "testuser";
 ConstCommandLine : String = "CMD.EXE";
 Title : WideString = "Test process";
 Domain : WideString = "WORKGROUP";
var
 MyStartupInfo : STARTUPINFO;
 ProcessInfo : PROCESS_INFORMATION;
 CommandLine : array[0..512] of WideChar;
begin
 FillChar(MyStartupInfo, SizeOf(MyStartupInfo), 0);
 MyStartupInfo.cb := SizeOf(MyStartupInfo);
 StringToWideChar(ConstCommandLine, CommandLine,
    Sizeof(CommandLine) div SizeOf(WideChar));
 MyStartupInfo.lpTitle := PWideChar(Title);
 if not CreateProcessWithLogonW (PWideChar(UserName), PWideChar(Domain),
     PWideChar(Password), LOGON_WITH_PROFILE, nil,
     CommandLine, 0, nil, nil, @MyStartupInfo, @ProcessInfo) then
   RaiseLastWin32Error()
 else begin
   CloseHandle(ProcessInfo.hProcess);
   CloseHandle(ProcessInfo.hThread);
 end;
end;


unit HSAdvApi;

interface
uses
 Windows;

function CreateProcessWithLogonW (const lpUsername : PWideChar;
 const lpDomain : PWideChar; const lpPassword : PWideChar;
 dwLogonFlags : DWORD; const lpApplicationName : PWideChar;
 lpCommandLine : PWideChar; dwCreationFlags : DWORD;
 lpEnvironment : Pointer; const lpCurrentDirectory : PWideChar;
 lpStartupInfo : PStartupInfo;
 lpProcessInfo : PProcessInformation) : Boolean; stdcall;

const
 LOGON_WITH_PROFILE = $00000001;
 LOGON_NETCREDENTIALS_ONLY = $00000002;
 LOGON_ZERO_PASSWORD_BUFFER = $80000000;

implementation
uses
 SysUtils;

{ ADVAPI32.DLL functions }
type
 TCreateProcessWithLogonW =
   function (const lpUsername : PWideChar;
 const lpDomain : PWideChar; const lpPassword : PWideChar;
 dwLogonFlags : DWORD; const lpApplicationName : PWideChar;
 lpCommandLine : PWideChar; dwCreationFlags : DWORD;
 lpEnvironment : Pointer; const lpCurrentDirectory : PWideChar;
 lpStartupInfo : PStartupInfo;
 lpProcessInfo : PProcessInformation) : Boolean; stdcall;

const
 DllName = "advapi32.dll";

var
 DllHandle : THandle;
 _CreateProcessWithLogonW : TCreateProcessWithLogonW;

function InitLib : Boolean;
begin
 if DllHandle = 0 then
   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
     DllHandle := LoadLibrary(DllName);
     if DllHandle <> 0 then begin
       @_CreateProcessWithLogonW := GetProcAddress(DllHandle,
         "CreateProcessWithLogonW");
     end;
   end;
 Result := (DllHandle <> 0);
end;

function NotImplementedBool : Boolean;
begin
 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
 Result := false;
end;

function CreateProcessWithLogonW (const lpUsername : PWideChar;
 const lpDomain : PWideChar; const lpPassword : PWideChar;
 dwLogonFlags : DWORD; const lpApplicationName : PWideChar;
 lpCommandLine : PWideChar; dwCreationFlags : DWORD;
 lpEnvironment : Pointer; const lpCurrentDirectory : PWideChar;
 lpStartupInfo : PStartupInfo;
 lpProcessInfo : PProcessInformation) : Boolean; stdcall;
begin
 if InitLib and Assigned(_CreateProcessWithLogonW) then
   Result := _CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword,
     dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags,
     lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInfo)
 else
   Result := NotImplementedBool;
end;

initialization
finalization
 if DllHandle <> 0 then
   FreeLibrary(DllHandle);
end.


 
GuAV ©   (2004-10-30 17:40) [3]

Игорь Шевченко ©   (30.10.04 17:10) [2]

Да, согласен, это лучше чем [1] но мне кажется что есть маленькая неточность здесь:


lpProcessInfo : PProcessInformation) : Boolean; stdcall;


ИМХО лучше написать BOOL.


 
Игорь Шевченко ©   (2004-10-30 18:18) [4]

GuAV ©   (30.10.04 17:40) [3]

На чем основывается IMHO ?


 
GuAV ©   (2004-10-30 18:39) [5]

Игорь Шевченко ©   (30.10.04 18:18) [4]
На чем основывается IMHO ?


BOOL <> Boolean. BOOL = LongBool. в модуле Windows.pas для внешних функций использован именно BOOL. Различия доступны по LongBool+F1

У BOOL любое не нулевое значение истина, например 65536. В Вашем коде вероятно компилятор сделает проверку вида TEST AL, AL. Что даст результат False.

Это ещё не всё. В VCL есть места где использована конструкция array[boolean] of...

Некоторые имеют нехорошую привычку писать if .. =true then. Всё же для boolean она должна работать.

Вы можете показать листинг функции CreateProcessWithLogonW где будет MOV EAX, 1 или что-то типа того. Однако это не показатель, т.к. это не документированно и не гарантированно для будущих версий этой dll.

Всё эт было ИМХО, если я ошибаюсь, опровергните.


 
GuAV ©   (2004-10-30 19:06) [6]

следующий пример демонсрирует разницу между BOOL и Boolean наглядно.

{$O-}  // не делает
{$O+} // разницы

function b1: boolean;
asm
 mov eax, 4
end;

function b2: boolean;
asm
 mov eax, 1
end;

function b3: BOOL;
asm
 mov eax, 4
end;

function b4: BOOL;
asm
 mov eax, 1
end;

function b5: boolean;
asm
 mov eax, 256
end;

function b6: BOOL;
asm
 mov eax, 256
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 if b1 = b2 then showmessage("b1 = b2"); // не выпадет
 if b3 = b4 then showmessage("b3 = b4"); // выпадет
 if b5 then showmessage("b5"); // не выпадет
 if b6 then showmessage("b6"); // выпадет
end;


 
Игорь Шевченко ©   (2004-10-30 19:24) [7]

GuAV ©   (30.10.04 19:06) [6]

Смотрим в Windows.pas и видим

type
 BOOL = LongBool;

Смотрим в описание функции CreateProcessWithLogonW и видим:

"If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero".

Для того, чтобы отличить Zero от NonZero в данном случае типа Boolean достаточно.

Кстати, не советую сравнивать результат функции с константой True - равенство никогда не выполнится, так как LongBool(True) равно -1, а функции Windows в случае успеха чаще всего возвращают 1.


 
Игорь Шевченко ©   (2004-10-30 19:32) [8]


> У BOOL любое не нулевое значение истина, например 65536.
> В Вашем коде вероятно компилятор сделает проверку вида TEST
> AL, AL. Что даст результат False.


Убедительно.


> Вы можете показать листинг функции CreateProcessWithLogonW
> где будет MOV EAX, 1 или что-то типа того. Однако это не
> показатель, т.к. это не документированно и не гарантированно
> для будущих версий этой dll.


Кстати, гарантировано. Если только не переопределят константу TRUE в stdlib.h

А это из Delphi:

" If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of nonzero ordinality to True."

То есть, в данном случае допустимо использовать и Boolean и BOOL.

Borland сам объявляет некоторые функции, возвращающие тип Boolean, в то время, как согласно MSDN тип их возвращаемого значения BOOL, например, UpdateLayeredWindow, SetLayeredWindowAttributes :)


 
GuAV ©   (2004-10-30 20:52) [9]

Кстати, не советую сравнивать результат функции с константой True - равенство никогда не выполнится, так как LongBool(True) равно -1, а функции Windows в случае успеха чаще всего возвращают 1.

Сравнение корректно. см сравнение b3 и b4 в [6].


> Для того, чтобы отличить Zero от NonZero в данном
> случае типа Boolean достаточно.

см. пример с 65536.

>Кстати, гарантировано. Если только не переопределят константу TRUE в stdlib.h

function IsWindowInt(hWnd: HWND): Integer; stdcall; external
 user32 name "IsWindow";

procedure TForm1.Button1Click(Sender: TObject);
const x: longbool = true;
begin
 ShowMessage(IntToHex(IsWindowInt(Handle), 8));
 ShowMessage(IntToHex(IsWindowInt(Application.Handle), 8));
end;


" If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of nonzero ordinality to True."

Именно. Но только для "a value of type ByteBool, LongBool, or WordBool"

Вот пример

function IsWindowBool(hWnd: HWND): BOOL; stdcall; external
 user32 name "IsWindow";

function IsWindowBoolean(hWnd: HWND): Boolean; stdcall; external
 user32 name "IsWindow";

procedure TForm1.Button2Click(Sender: TObject);
begin
 if IsWindowBool(Handle) = True then
   ShowMessage("BOOL можно сравнивать так"); //выпадет
 if IsWindowBoolean(Handle) = True then
   ShowMessage("Boolean можно сравнивать так"); //не  выпадет
end;



> Borland сам объявляет некоторые функции, возвращающие
> тип Boolean, в то время, как согласно MSDN тип их
> возвращаемого значения BOOL, например,
> UpdateLayeredWindow, SetLayeredWindowAttributes :)

БАГ !

_________________________

Надо называть вещи своими именами. Boolean - Booleanом, BOOL - BOOLом. В противном случае это грабли.


 
Defunct ©   (2004-10-30 22:00) [10]

Спор про какую-то чипуху.
Если 0 четко определен, на этом можно поставить точку.

Если вдруг будет значение 65536 сравнение должно производиться как test Eax, Eax.

> function b5: boolean;
> asm
>  mov eax, 256


Это неудачный пример, boolean - байт, вы его задаете 0-м, вот и имеете ерунду на выходе.

Сделайте по-нормальному:
Xor Eax, Eax
Dec Eax

Более того придирательство было к:
> lpProcessInfo : PProcessInformation) : Boolean; stdcall;

if Boolean=True then BOOL = True тем более

> В Вашем коде вероятно компилятор сделает проверку вида TEST
> AL, AL. Что даст результат False.

В его случае компилятор сделает приведение типов BOOL -> Boolean перед проверкой.

>> Borland сам объявляет некоторые функции, возвращающие
>> тип Boolean, в то время, как согласно MSDN тип их

> БАГ !

Еще раз, будьте попроще. А то все это похоже на поиск золота на помойке.


 
Игорь Шевченко ©   (2004-10-30 22:15) [11]

GuAV ©   (30.10.04 20:52) [9]

"function IsWindowInt(hWnd: HWND): Integer; stdcall; external
user32 name "IsWindow";

procedure TForm1.Button1Click(Sender: TObject);
const x: longbool = true;
begin
ShowMessage(IntToHex(IsWindowInt(Handle), 8));
ShowMessage(IntToHex(IsWindowInt(Application.Handle), 8));
end;"

Запустил - получил оба раза единицу. Что я делаю не так ?

Врочем, пусть нас рассудит опыт - возьми как можно больше функций, объявленных в PSDK как BOOL и посмотри, какое значение они возвращают. Всем будет интересно, и тебе и мне.


 
Defunct ©   (2004-10-30 22:18) [12]

Function BoolTrue:Bool;assembler;
asm
 mov Eax, 65536
end;

procedure TForm1.Button1Click(Sender: TObject);
var B:Boolean;
begin
 B := BoolTrue;
 If B Then ShowMessage("&#215;&#232;&#245;&#224;&#242;&#252; &#237;&#224; Bool");
end;


 
Defunct ©   (2004-10-30 22:19) [13]

[12]
Function BoolTrue:Bool;assembler;
asm
mov Eax, 65536
end;

procedure TForm1.Button1Click(Sender: TObject);
var B:Boolean;
begin
B := BoolTrue;
If B Then ShowMessage("Чихать на Bool c Эйфелевой башни");
end;


 
Игорь Шевченко ©   (2004-10-30 22:27) [14]

Defunct ©   (30.10.04 22:19) [13]

Мы все-таки речь ведем о функциях Windows, не надо забывать.


 
Defunct ©   (2004-10-30 22:29) [15]

> Запустил - получил оба раза единицу. Что я делаю не так ?

Не в единице дело Игорь. Чтобы потерять значение неравное нулю и каким-то чудом получить нуль, надо быть Guru.. Пример [13] - наглядная демонстрация того что, код [2] в любом случае будет работать, пусть там хоть 65536 будет возвращаться функцией _CreateProcessWithLogonW.


 
GuAV ©   (2004-10-30 22:35) [16]

Defunct ©   (30.10.04 22:19) [13]
Function BoolTrue:Bool;assembler;
asm
mov Eax, 65536
end;

procedure TForm1.Button1Click(Sender: TObject);
var B:Boolean;
begin
B := BoolTrue;
If B Then ShowMessage("Чихать на Bool c Эйфелевой башни");
end;


В Вашем примере нет той ошибки, Вы написали Bool

Попробуйте так
Function BoolTrue: Boolean;assembler;
asm
mov Eax, 65536
end;

procedure TForm1.Button1Click(Sender: TObject);
var B:Boolean;
begin
B := BoolTrue;
If B Then ShowMessage("Чихать на Bool c Эйфелевой башни");
end;


Игорь Шевченко ©   (30.10.04 22:15) [11]
Игорь, представлеете, а у меня в win98 не 1.


 
Игорь Шевченко ©   (2004-10-30 22:46) [17]

GuAV ©   (30.10.04 22:35) [16]


> Игорь, представлеете, а у меня в win98 не 1.


Представляю. У меня Win2k, но меня оправдывает то, что функция CreateProcessWithLogonW, равно, как и функции, описанные Borland"ом, как Boolean, присутствуют только в Win2k и выше :)

Впрочем, я полагаю, нас рассудит цитата из Jedi Win32 API translation.

"The implementation of CreateMutex only interpretes bInitialOwner as True if it"s ordinal value is 1, all other values are interpreted as False. Delphi compiles Longbool(True) as $FFFFFFFF which is consequently interpreted as False. Changing the bInitalOwner parameter type to Boolean fixes the problem (Boolean(True) = 1) but that would be implementation specific and might break in the future, though unlikely."

В целом вы правы, но в конкретном случае (CreateProcessWithLogonW) я оставляю за собой право объявлять результат, как Boolean.


 
GuAV ©   (2004-10-30 23:07) [18]

Я тем временем проверил ряд функций в 98 и XP.
Все возвращали 1 в ХР, но ни одна в 98 !

Игорь Шевченко ©   (30.10.04 22:46) [17]
функция CreateProcessWithLogonW, равно, как и функции, описанные Borland"ом, как Boolean, присутствуют только в Win2k и выше :)


Очень похоже


> Delphi compiles Longbool(True) as $FFFFFFFF which is
> consequently interpreted as False. Changing the
> bInitalOwner parameter type to Boolean fixes the
> problem


Никакой проблемы нет при получении результата 1.
Пример.
procedure TForm1.Button1Click(Sender: TObject);
var
 B1, B2: BOOL;
 I1: Integer absolute B1;
 I2: Integer absolute B2;
begin
 I1:=-1;
 I2:=1;
 if B1 = B2 then ShowMessage("А по фиг !");
end;


Что насчёт передачи параметров, то имхо раз пошло такое дело что 2k и новее используют 1, им вероятно следует всегда передавать 1, всегда писать boolean, вреда от этого точно не будет, а польза - возможно будет.


> В целом вы правы, но в конкретном случае
> (CreateProcessWithLogonW) я оставляю за собой право
> объявлять результат, как Boolean.


Ваше право теперь признаю :)

зы: А всё же, хорошие грабли, учитывая что разрабочтик обычно юзает 2k/XP, а юзер - шо попало ;)


 
GuAV ©   (2004-10-30 23:14) [19]


> всегда писать boolean

при передаче, и никогда в качестве результата, если функция есть в 9х.

Хотя тут я тоже вижу проблему.

Boolean - 1 байт, часто выставляется типа SETNZ AL, остальные 3 байта не определены.

Я бы решил проблему в CreateMutex так:
const BOOL_TRUE = BOOL(1);


 
Игорь Шевченко ©   (2004-10-30 23:24) [20]

GuAV ©   (30.10.04 23:14) [19]

Раз уж зашел разговор, то могу рассказать о тех граблях, на которые я наткнулся, работая с NLS-функциями в Windows (EnumLanguageGroups, EnumCodePages и прочие enumerators).
callback-функции, передаваемые в качестве параметра, объявлены, как возвращающие результат типа BOOL. Для продолжения перечисления они должны возвратить, согласно MSDN, ненулевое значение (там указано, что to continue enumeration, the callback function should return TRUE).

Так вот, True эти функции должны возвращать Сишное, то есть 1. Причем, внутри этих функций (Enumxxxx) стоит сравнение с именно с единицей, а не с неким "ненулевым значением".


 
GuAV ©   (2004-10-30 23:34) [21]

Игорь Шевченко ©   (30.10.04 23:24) [20]

Опять же рекомендую не Boolean, а
const BOOL_TRUE = BOOL(1);

И вероятно Borland"у следует исправить ord(LongBool(True)) с -1 на 1.

И может выводы из этой ветки поместить например в FAQ ?


 
Игорь Шевченко ©   (2004-10-30 23:50) [22]

GuAV ©   (30.10.04 23:34) [21]


> Опять же рекомендую не Boolean, а
> const BOOL_TRUE = BOOL(1);


Я нашел альтернативный выход, но идея хорошая. Только я бы назвал не BOOL_TRUE, а MsBOOL или WinBOOL :)


> И может выводы из этой ветки поместить например в FAQ ?


Да, поддерживаю.


 
GuAV ©   (2004-10-30 23:55) [23]

Игорь Шевченко ©   (30.10.04 23:24) [20]

Интересно, а есть ли вообще функции winapi, принимающие BOOL(-1) ?

И смотрите как пишут:
как результат - zero или nonzero
как пеарметр - TRUE или FALSE.


 
Игорь Шевченко ©   (2004-10-31 00:00) [24]

GuAV ©   (30.10.04 23:55) [23]

Есть функции, которые честно сравнивают результат с нулем, и все от него отличное, интерпретируют как True, для примера, EnumWindows, EnumWindowStations и т.п.


 
GuAV ©   (2004-10-31 00:04) [25]

Игорь Шевченко ©   (30.10.04 23:50) [22]
WinBOOL

const
 WIN_NT_FALSE = BOOL(0);
 WIN_NT_TRUE = BOOL(1);

function BoolToWin(B: Boolean): BOOL; overload;
asm
 AND  EAX, 00000001h
end;

{
function BoolToWin(B: BOOL): BOOL; overload;
asm
 TEST EAX, EAX
 SETNZ AL
 AND  EAX, 00000001h
end;
}

function BoolToWin(B: BOOL): BOOL; overload;
asm
 TEST EAX, EAX
 JZ   @@Exit
 MOV  EAX, 00000001h
 @@Exit:
end;



 
GuAV ©   (2004-10-31 00:09) [26]

или не, во как:

function BoolToWin(B: Boolean): BOOL; overload;
asm
AND  EAX, 00000001h
end;

function BoolToWin(B: ByteBool): BOOL; overload;
asm
TEST AL, AL
JZ   @@Exit
MOV  EAX, 00000001h
@@Exit:
end;

function BoolToWin(B: WordBool): BOOL; overload;
asm
TEST AX, AX
JZ   @@Exit
MOV  EAX, 00000001h
@@Exit:
end;

function BoolToWin(B: LongBool): BOOL; overload;
asm
TEST EAX, EAX
JZ   @@Exit
MOV  EAX, 00000001h
@@Exit:
end;


 
GuAV ©   (2004-10-31 00:17) [27]


> function BoolToWin(B: ByteBool): BOOL; overload;


> function BoolToWin(B: WordBool): BOOL; overload;

С этими точнее как я написал не получится - надо так:
function BoolToWin(B: ByteBool): BOOL; overload;
asm
TEST AL, AL
SETNZ AL
AND  EAX, 00000001h
end;

function BoolToWin(B: WordBool): BOOL; overload;
asm
TEST AX, AX
SETNZ AL
AND  EAX, 00000001h
end;


 
GuAV ©   (2004-10-31 01:39) [28]

Какая разница между Boolean и BOOL ?
Как использовать внешние функции, работающие с логическими значениями ?

В Borland Delphi основным логическим типом является boolean. Длина его 1 байт. Если этот байт равен единице, то значение логического типа - истина, если нулю, то ложь. Другие значения являются недопустимыми, и их использование может привести к неожиданным результатам. Пример неожиданных результатов:

function b1: boolean;
asm
mov eax, 4 //недопустимое значение
end;

function b2: boolean;
asm
mov eax, 1
end;

function b3: boolean;
asm
mov eax, 256 //недопустимое значение
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if b1 = b2 then showmessage("b1 = b2"); // не выпадет
if b3 then showmessage("b3"); // не выпадет
end;

Для совместимости с другими языками введены ещё три логических типа - LongBool, WordBool и ByteBool. Размер их соответственно 1, 2 и 4 байта. LongBool значение - истинна если LongWord не равен 0 и ложь если равен 0. Для WordBool и ByteBool соответсвенно Word и Byte.

Для типа LongBool приведенный выше пример работает, т.к. значения 4 (не допустимые для Boolean) и 256 (не соответсвующее разрядности Boolean) будут истиной для LongBool

function b1: LongBool;
asm
mov eax, 4
end;

function b2: LongBool;
asm
mov eax, 1
end;

function b3: LongBool;
asm
mov eax, 256
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if b1 = b2 then showmessage("b1 = b2"); // выпадет
if b3 then showmessage("b3"); // выпадет
end;


Константам True типов LongBool, WordBool и ByteBool соответствуют значения $FFFFFFFF, $FFFF и $FF.

Логические операции над Boolean эффективнее, чем над XxxxBool, т.к. сводятся к соответствующим побитным операциям. Кроме того Boolean упорядочен, ord(False)=0 ord(True)=1. Поэтому предпочтительно использовать Boolean.

В 32-разрядной Windows принят 32-разрядный логический тип, с ненулевым значением в качестве истины. Причём в win9x это ненулевое значение произвольно, однако, начиная с Windows 2000, оно строго равно единице.

В Delphi этот тип объявлен как  type BOOL = LongBool;

Так, следующее объявление было бы не корректно в 9х:

function IsWindow(hWnd: HWND): Boolean; stdcall; external
user32 name "IsWindow";


Однако, оно корректно в 2000, поскольку при приведении LongWord к Byte отсекаются страшие байты, и следовательно если LongWord был равен 1, то и Byte будет равен 1, аналогично c 0.

Для всех ОС подойдёт такое объявление:

function IsWindow(hWnd: HWND): BOOL; stdcall; external
user32 name "IsWindow";

Для функций появившихся в Windows 2000 оба объявления корректны. Поэтому, исходя из того, что Boolean предпочтительнее в Delphi их лучше объявлять с результатом Boolean.

Теперь о передаче параметров. Как сообщалось ранее, в Windows принят 32-разрядный логический тип, с ненулевым значением в качестве истины. Т.е. вроде бы любое значение не равное нулю  должно сойти за истину. Однако есть функции, которые требуют, чтобы в качестве "любого значение не равное нулю" передавалась единица. Т. е. константа True = $FFFFFFFF не подойдёт. Использовать Boolean тоже не следует, т.к. старшие 3 байта будут не определены и при попытке передать False может передаваться значение отличное от 0, что тоже может иметь негативные последствия. Решение - или объявлять этот параметр как DWORD или использовать константу

const WIN_TRUE=BOOL(1);


 
VMcL ©   (2004-10-31 02:07) [29]

>>GuAV ©  (31.10.04 01:39) [28]

>Для совместимости с другими языками введены ещё три логических типа - LongBool, WordBool и ByteBool. Размер их соответственно 1, 2 и 4 байта.

С точностью до наоборот: 4, 2 и 1.

>function b3: boolean;

Неудачный пример. Byte(256) = 0.

>// выпадет

Кхм. Обычно пишут что-то типа "этот оператор не выполнится". А то как-то непонятно, кто выпадет, откуда и куда.

>>Игорь Шевченко ©  (30.10.04 23:24) [20]

>Причем, внутри этих функций (Enumxxxx) стоит сравнение с именно с единицей, а не с неким "ненулевым значением".

Вот яркий пример людей, который вместо
if (a) {...}
и
if (!a) {...}
пишут
if (a == TRUE) {...}
и
if (a == FALSE) {...}
соотвественно.

Повбывав бы :-)


 
GuAV ©   (2004-10-31 02:10) [30]


>const WIN_TRUE=BOOL(1);

Идея хорошая но не работает !

Работает так:

const
 WIN_TRUE_VALUE: LongWord = 1;
var
 WIN_TRUE: BOOL absolute WIN_TRUE_VALUE;


 
GuAV ©   (2004-10-31 02:13) [31]

VMcL ©   (31.10.04 2:07) [29]
Неудачный пример. Byte(256) = 0.


Именно об этом речь. Такое значение может вернуть BOOL-функция в 9х. DWord не равен 0, а байт - равен.


> С точностью до наоборот: 4, 2 и 1.

угу.


> Кхм. Обычно пишут что-то типа "этот оператор не
> выполнится". А то как-то непонятно, кто выпадет,
> откуда и куда

ок. "этот оператор не выполнится".


 
Defunct ©   (2004-10-31 02:23) [32]

GuAV ©   (31.10.04 02:13) [31]
> Такое значение может вернуть BOOL-функция в 9х.

Я очень в этом сомневаюсь.
скорее там будет 255 не так ли?

У вас w98 скажите често, что возвращает функция?

VMcL ©   (31.10.04 02:07) [29]
чаще видел:
if a != 0 {...}
if a == 0 {...}
реже видел:
if a != 1 {...}

хотя в общем с вами согласен, проверка с 1 это клиника.


 
GuAV ©   (2004-10-31 02:33) [33]


> скорее там будет 255 не так ли?

Не так.
function IsWindowInt(hWnd: HWND): Integer; stdcall; external
user32 name "IsWindow";

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Add(Format("%.8X %.8X", [Handle, IsWindowInt(Handle)]));
with Application do
Memo1.Lines.Add(Format("%.8X %.8X", [Handle, IsWindowInt(Handle)]));
end;


Результат.
00000A48 82198090
00000A20 82198EF8


Позакрывал немонго окон. Ещё раз результат.
0000046C 821999A4
00000770 82199C7C


И где-то так же для других функций.


> хотя в общем с вами согласен, проверка с 1 это клиника.

Вы представляете, с этим и я согласен.


 
GuAV ©   (2004-10-31 02:34) [34]

GuAV ©   (31.10.04 2:33) [33]
Позакрывал немонго окон. Ещё раз результат.

Забыл сказать, что перезапустил - иначе хэндлы бы не поменялись, конечно.


 
Defunct ©   (2004-10-31 02:36) [35]

> Позакрывал немонго окон. Ещё раз результат.

мда.. не зря некоторые говорили масдай..


 
GuAV ©   (2004-10-31 02:49) [36]

Defunct ©   (31.10.04 2:36) [35]
мда.. не зря некоторые говорили масдай..

Ну я же перезапустил. Поэтому Хэндлы другие и сами окна другие. А значение ISWindow видимо больше чем просто BOOL, имеет физический смысл :-))


 
Anatoly Podgoretsky ©   (2004-10-31 09:57) [37]

VMcL ©   (31.10.04 02:07) [29]
Вот на подобных методах работы пострадало много программистов, когда сменилось определение контстанты TRUE в языке или возвращаемое значение из ОС.
Это пример опасного программирования, который выявляется не в момент написания, а иногда только несколько лет спустя.

Относительно безопасно передачи в качестве параметра, но совершенно не допустимо сравнение или другие операции с константой TRUE. Гарантирована только константа FALSE и правильная работа с ней во всех случаях. В других случаях если требуется работа с TRUE оно должно заменяться на arg <> FALSE


 
VMcL ©   (2004-10-31 10:35) [38]

>>Defunct ©  (31.10.04 02:23) [32]
>хотя в общем с вами согласен, проверка с 1 это клиника.
>>GuAV ©  (31.10.04 02:33) [33]
>Вы представляете, с этим и я согласен.

Вот и я пытался объяснить alena.svt © здесь:
http://delphimaster.net/view/1-1099061998/
Только как горохом об стенку. Дело вкуса, дело вкуса, блин. За такие вкусы надо к стенке и расстреливать... из водяного пистолета :-)


 
Игорь Шевченко ©   (2004-10-31 13:05) [39]

GuAV ©   (31.10.04 02:10) [30]


> Работает так:
>
> const
>  WIN_TRUE_VALUE: LongWord = 1;
> var
>  WIN_TRUE: BOOL absolute WIN_TRUE_VALUE;


Честно говоря, страдаю идиосинкразией к слову absolute, не знаю, почему, но факт :)


 
GuAV ©   (2004-10-31 13:15) [40]

VMcL ©   (31.10.04 10:35) [38]
Относительно безопасно передачи в качестве параметра, но совершенно не допустимо сравнение или другие операции с константой TRUE. Гарантирована только константа FALSE и правильная работа с ней во всех случаях. В других случаях если требуется работа с TRUE оно должно заменяться на arg <> FALSE


В принципе, сравнивать в С я смысла вообще не вижу.
В Delphi есть смысл сравнивать, например хэндлы или указатели, чтобы избежать необходимости приведения типов. Ptr <> nil почему-то лучше чем BOOL(Ptr).
Но сравнивают действительно не Handle = 1, а Handle <> 0, иначе просто не работает.

Что интересно, в отличии от С, в Delphi есть защита от этих граблей
см. код в [18].
В С различается логическое и побитное and or not. Почему же нет такого xor и сравения ?



Страницы: 1 2 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.68 MB
Время: 0.039 c
14-1101124907
Comp
2004-11-22 15:01
2004.12.12
Инсталяция Turbo Assembler 5.0


3-1100241022
gek
2004-11-12 09:30
2004.12.12
Узнать формат базы данных


4-1098956217
Cheburek
2004-10-28 13:36
2004.12.12
Как создать виртуальный СD ? Как написать драйвер ?


1-1101489554
Frozzen
2004-11-26 20:19
2004.12.12
Работа с MemProof


3-1100276805
jiura334
2004-11-12 19:26
2004.12.12
Как сделать активной N-ую строку TDbGrid?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский