![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запуск команды runas [D4, D6, WinXP]
olevacho © (2004-10-30 15:56:00)Есть в винде ХР команда runas. Она позволяет находясь в системе под одним пользователем выполнить другую команду или внешнюю программу от имени другого пользователя. Проблемма в том что нужно после запуска вводить пароль другого пользователя вручную. Можно ли сделать прогу на дельфе так чтоб пароль другого пользователя передавался из моей проге команде runas автоматически. А может в дельфе есть какой-нить аналог команды runas ?
GuAV (2004-10-30 23:34:00) [21]Игорь Шевченко © (30.10.04 23:24) [20]
Опять же рекомендую не Boolean, а
const BOOL_TRUE = BOOL(1);
И вероятно Borland'у следует исправить ord(LongBool(True)) с -1 на 1.
И может выводы из этой ветки поместить например в FAQ ?
Игорь Шевченко (2004-10-30 23:24:00) [22]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:14:00) [23]
> всегда писать boolean
при передаче, и никогда в качестве результата, если функция есть в 9х.
Хотя тут я тоже вижу проблему.
Boolean - 1 байт, часто выставляется типа SETNZ AL, остальные 3 байта не определены.
Я бы решил проблему в CreateMutex так:
const BOOL_TRUE = BOOL(1);
GuAV (2004-10-30 23:07:00) [24]Я тем временем проверил ряд функций в 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, а юзер - шо попало ;)
Игорь Шевченко (2004-10-30 22:46:00) [25]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 22:35:00) [26]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.
Defunct (2004-10-30 22:29:00) [27]> Запустил - получил оба раза единицу. Что я делаю не так ?
Не в единице дело Игорь. Чтобы потерять значение неравное нулю и каким-то чудом получить нуль, надо быть Guru.. Пример [13] - наглядная демонстрация того что, код [2] в любом случае будет работать, пусть там хоть 65536 будет возвращаться функцией _CreateProcessWithLogonW.
Игорь Шевченко (2004-10-30 22:27:00) [28]Defunct © (30.10.04 22:19) [13]
Мы все-таки речь ведем о функциях Windows, не надо забывать.
Defunct (2004-10-30 22:19:00) [29][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;
Defunct (2004-10-30 22:18:00) [30]
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;
Игорь Шевченко (2004-10-30 22:15:00) [31]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:00:00) [32]Спор про какую-то чипуху.
Если 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 тип их
> БАГ !
Еще раз, будьте попроще. А то все это похоже на поиск золота на помойке.
GuAV (2004-10-30 20:52:00) [33]Кстати, не советую сравнивать результат функции с константой 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ом. В противном случае это грабли.
Игорь Шевченко (2004-10-30 19:32:00) [34]
> У 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 :)
Игорь Шевченко (2004-10-30 19:24:00) [35]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.
GuAV (2004-10-30 19:06:00) [36]следующий пример демонсрирует разницу между 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;
GuAV (2004-10-30 18:39:00) [37]Игорь Шевченко © (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.
Всё эт было ИМХО, если я ошибаюсь, опровергните.
Игорь Шевченко (2004-10-30 18:18:00) [38]GuAV © (30.10.04 17:40) [3]
На чем основывается IMHO ?
GuAV (2004-10-30 17:40:00) [39]Игорь Шевченко © (30.10.04 17:10) [2]
Да, согласен, это лучше чем [1] но мне кажется что есть маленькая неточность здесь:
lpProcessInfo : PProcessInformation) : Boolean; stdcall;
ИМХО лучше написать BOOL.
Игорь Шевченко (2004-10-30 17:10:00) [40]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.