Форум: "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.hfunction 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("×èõàòü íà 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]
WinBOOLconst
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) будут истиной для LongBoolfunction 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 и сравения ?
← →
GuAV © (2004-10-31 13:35) [41]Игорь Шевченко © (31.10.04 13:05) [39]
Честно говоря, страдаю идиосинкразией к слову absolute, не знаю, почему, но факт :)
Ну можно ещё объявить как переменную и установить в initialization или сделать функцией :)
Или вообще такtype
WIN_BOOL = type DWORD;
const
WIN_FALSE = 0;
WIN_TRUE = 1;
Страницы: 1 2 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];
Память: 0.68 MB
Время: 0.052 c