Головна сторінка
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 і бачимо

тип
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;
починати
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;
асм
mov Eax, 65536
end;

procedure TForm1.Button1Click (Sender: TObject);
var B: Boolean;
починати
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);

Ідея хороша але не працює!

Працює так:

сопзЬ
WIN_TRUE_VALUE: LongWord = 1;
було
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.78 MB
Час: 0.127 c
1-1101715306
Molchanov
2004-11-29 11:01
2004.12.12
Видалення рядків з TRichEdit


3-1100082557
alsov1
2004-11-10 13:29
2004.12.12
Не виходить змусити фільтрувати TADOQuery


14-1100766445
BiN
2004-11-18 11:27
2004.12.12
Опитування. Географія форумчан.


3-1100619712
~ Blade ~
2004-11-16 18:41
2004.12.12
Оновлення таблиці в адо


9-1091815630
Антон
2004-08-06 22:07
2004.12.12
[GLScene]: TMemoryStream





африкаанс албанський арабська вірменин азербайджанець баскський білоруський болгарська каталонський Китайська (спрощене письмо) Китайський традиційний) хорватський чеська данську мову нідерландський Ukranian естонець Філіппінська фінську мову французький
галісійська грузинський німецький грецький гаїтянський креольський давньоєврейську хінді угорський ісландський індонезієць ірландський італійський японський корейський латиська литовець македонець малайський мальтійський норвежець
перс полірування португальська румунський російська сербський словацький словенський іспанська суахілі шведську мову тайський турецька український урду в&#39;єтнамський валлійський ідиш бенгальський боснійський
кебуано есперанто гуджараті хауса хмонг ігбо яванський каннада кхмерская Лао латинь маорі маратхі монгольський непальська панджабі сомалійський тамільська телугу йоруба
зулуський
Англійська Французький Німецький Італійський Португальська Русский Іспанська