Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Запуск команды runas [D4, D6, WinXP]


Страницы:   1 2 3

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.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо