V>И здесь si — это указатель на структуру? :no: :no: :no: V>Указатель будет PStartupInfo, в ПРАВИЛЬНО описанную функцию (а не как у вас) надо передавать @si
Ктстати говоря...
Что CreateProcessWithLogonW за меня и юзера в windowstation и desktop добавит?
Раньше все это руками приходилось делать. МОжет в этом дело? Моет надо в si добавлять инфу про того юзера от которого запускаем?
Re[5]: Как запустить программу от имени пользователя
procedure TForm1.Button1Click(Sender: TObject);
var hLib:THandle;
CreateProcessWithLogon : TCreateProcessWithLogonW;
si : _STARTUPINFOA;
pi : Process_Information;
begin
hLib:=LoadLibrary('advapi32.dll');
ZeroMemory(@Si,Sizeof(si));
si.cb:=SizeOf(si);
CreateProcessWithLogon:=GetProcAddress(hLib,'CreateProcessWithLogonW');
Здравствуйте ZZ, Вы писали:
ZZ>Я не очень понял, решили вы тут проблему или нет Поэтому предложу вариант
ZZ>type ZZ> TCreateProcessWithLogonW = function( ZZ> lpUsername : PWideChar; ZZ> lpDomain : PWideChar; ZZ> lpPassword : PWideChar; ZZ> dwLogonFlags : DWORD; ZZ> lpApplicationName : PWideChar; ZZ> lpCommandLine : PWideChar; ZZ> dwCreationFlags : DWORD; ZZ> lpEnvironment : Pointer; ZZ> lpCurrentDirectory : PWideChar; ZZ> const lpStartupInfo : _STARTUPINFOA; ZZ> var lpProcessInfo : PROCESS_INFORMATION):BOOL;stdcall;
ZZ>procedure TForm1.Button1Click(Sender: TObject); ZZ>var hLib:THandle; ZZ> CreateProcessWithLogon : TCreateProcessWithLogonW; ZZ> si : _STARTUPINFOA; ZZ> pi : Process_Information; ZZ>begin ZZ> hLib:=LoadLibrary('advapi32.dll'); ZZ> ZeroMemory(@Si,Sizeof(si)); ZZ> si.cb:=SizeOf(si); ZZ> CreateProcessWithLogon:=GetProcAddress(hLib,'CreateProcessWithLogonW');
ZZ> CreateProcessWithLogon('login',nil,'password',1,nil,'cmd.exe',0,nil,nil,si,pi);
ZZ>end;
Ты чисто теоретически предлагаешь, или это у тебя заработало? Если первое — тебя сейчас забьёт vasketsov и будет совершенно прав, т.к. ни один из его советов (обобщённых Vi2, но он тебя, наверное, трогать не будет, т.к. более терпелив) ты не учёл. Если второе — скорее всего произошло чудо, попробуй запустить ещё раз. Если всё равно получилось — дико извиняюсь за наглый тон, видимо чего-то я сильно не понимаю.
Делай что должно, и будь что будет
Re[3]: Как запустить программу от имени пользователя
Здравствуйте SergH, Вы писали:
SH>Здравствуйте ZZ, Вы писали:
ZZ>>Я не очень понял, решили вы тут проблему или нет Поэтому предложу вариант
ZZ>>type ZZ>> TCreateProcessWithLogonW = function( ZZ>> lpUsername : PWideChar; ZZ>> lpDomain : PWideChar; ZZ>> lpPassword : PWideChar; ZZ>> dwLogonFlags : DWORD; ZZ>> lpApplicationName : PWideChar; ZZ>> lpCommandLine : PWideChar; ZZ>> dwCreationFlags : DWORD; ZZ>> lpEnvironment : Pointer; ZZ>> lpCurrentDirectory : PWideChar; ZZ>> const lpStartupInfo : _STARTUPINFOA; ZZ>> var lpProcessInfo : PROCESS_INFORMATION):BOOL;stdcall;
ZZ>>procedure TForm1.Button1Click(Sender: TObject); ZZ>>var hLib:THandle; ZZ>> CreateProcessWithLogon : TCreateProcessWithLogonW; ZZ>> si : _STARTUPINFOA; ZZ>> pi : Process_Information; ZZ>>begin ZZ>> hLib:=LoadLibrary('advapi32.dll'); ZZ>> ZeroMemory(@Si,Sizeof(si)); ZZ>> si.cb:=SizeOf(si); ZZ>> CreateProcessWithLogon:=GetProcAddress(hLib,'CreateProcessWithLogonW');
ZZ>> CreateProcessWithLogon('login',nil,'password',1,nil,'cmd.exe',0,nil,nil,si,pi);
ZZ>>end;
SH>Ты чисто теоретически предлагаешь, или это у тебя заработало? Если первое — тебя сейчас забьёт vasketsov и будет совершенно прав, т.к. ни один из его советов (обобщённых Vi2, но он тебя, наверное, трогать не будет, т.к. более терпелив) ты не учёл. Если второе — скорее всего произошло чудо, попробуй запустить ещё раз. Если всё равно получилось — дико извиняюсь за наглый тон, видимо чего-то я сильно не понимаю.
Чисто практически. Не уверен только в 4 параметре "запускаемой"(не описания)(но с 1 он лучше смотрится
Может объяснишь, что тут не так?? Или ты тоже Delphi никогда не видел и "в pascalе ни бумбум" (ничего личного, просто подозреваю о чем речь). А всю дискуссию я не читал, только первые и последние сообщения....
Re[4]: Как запустить программу от имени пользователя
Значит, заработало?
ZZ>Не уверен только в 4 параметре "запускаемой"(не описания)(но с 1 он лучше смотрится :)) ZZ>Может объяснишь, что тут не так??
В конце.
ZZ>Или ты тоже Delphi никогда не видел и "в pascalе ни бумбум" (ничего личного, просто подозреваю о чем речь).
Видел, но давно. И бумбум, но тоже давно. Могу ошибаться.
ZZ> А всю дискуссию я не читал, только первые и последние сообщения.... :(
Напрасно.
Пытаюсь объяснить, что тут по-моему не так.
1. В правильном прототипе функции последние два параметра — указатели. В твоём прототипе последний параметр наверное будет указателем (точно не знаю, но вроде должен из-за var), но предпоследний — нет. И передаёшь ты его не как указатель. (Или delphi сама его преобразует?)
2. В правильном прототипе не STARTUPINFOA, а STARTUPINFOW
lpCommandLine
[in] Pointer to a null-terminated string that specifies the command line to execute. This function will fail if this parameter is a const string.
ты передаёшь 'cmd.exe'. Возможно, delphi размещает такие строки в куче (или ещё где-то), но сомневаюсь.
Делай что должно, и будь что будет
Re[6]: Как запустить программу от имени пользователя
Здравствуйте Vi2, Вы писали:
Vi2> lpStartupInfo: PStartupInfoW;
А где взять описание именно этой структуры (у меня в заголовках только _StartupInfoA)?
Vi2>У тебя вместо указателей описАны структуры. Vi2>Ребята! Вместо того чтобы ставить 0 отметили бы где ошибка — и вопрос м.б. был бы решён.
Сделал указатели. Все равно та же хрень.
Есть мысль насчет того что в StartupInfoW должен передаваться указатель на desktop и windowstation для того юзера которого мы логиним. А он у меня nil перед вызовом функции CreateProcessWithLogonW. Как сказано в MSDN, в статье
INFO: CreateProcessAsUser, Windowstations and Desktops :
When a process is launched via the CreateProcessAsUser API, the process will be launched into a windowstation and desktop combination based on the value of lpDesktop in the STARTUPINFO structure parameter. If a windowstation and desktop combination is specified in the lpDesktop member, the system will attempt to launch the process into that windowstation and desktop. If the lpDesktop member is initialized to NULL, the system will attempt to use the same windowstation and desktop as the calling process. If it is initialized with the empty string, "", the system will either create a new invisible windowstation and desktop or if one has been created via a prior call using the same access token, the existing windowstation and desktop will be used.
Так что мысль такая — надо как и вслучае использования CreateProcessAsUser давать доступ юзеру к десктопу и виндоустэйшну (получим указатель) и передавать его в структуру PStartupInfoW перед вызовом CreateProcessWithLogonW. Или CreateProcessWithLogonW сама должна все сделать?
Кто, что думает по этому поводу?
Re[5]: Как запустить программу от имени пользователя
Ага
ZZ>>Не уверен только в 4 параметре "запускаемой"(не описания)(но с 1 он лучше смотрится ZZ>>Может объяснишь, что тут не так??
SH>В конце.
Я так и подумал
SH>1. В правильном прототипе функции последние два параметра — указатели. В твоём прототипе последний параметр наверное будет указателем (точно не знаю, но вроде должен из-за var), но предпоследний — нет. И передаёшь ты его не как указатель. (Или delphi сама его преобразует?)
По моему, const и var — Это и есть "указатели"
SH>2. В правильном прототипе не STARTUPINFOA, а STARTUPINFOW
Знаю, но STARTUPINFOW в Windows.pas нету ( А самому описывать было лень... Но — SizeOf(STARTUPINFOA)=SizeOf(STARTUPINFOW) Или нет?? А в самих параметрах нет ни одной строки (ни ANSI ни Unicode) => разницы нет.
SH>3. В параметр lpCommandLine нельзя передавать константную строку. http://msdn.microsoft.com/library/en-us/dllproc/prothred_2gl3.asp — описание CreateProcessWithLogonW,
SH>lpCommandLine SH>[in] Pointer to a null-terminated string that specifies the command line to execute. SH>This function will fail if this parameter is a const string.
SH>ты передаёшь 'cmd.exe'. Возможно, delphi размещает такие строки в куче (или ещё где-то), но сомневаюсь.
А вот черт его знает, но поверь наслово — работает (если очень хочешь, могу выслать ехе, хотя врядли ты рискнешь его запустить
Re[7]: Как запустить программу от имени пользователя
Здравствуйте Maxus, Вы писали:
Vi2>> lpStartupInfo: PStartupInfoW;
M>А где взять описание именно этой структуры (у меня в заголовках только _StartupInfoA)?
Это странно. Неужели delphi не поддерживает unicode? Но в любом случае они почти обинаковы, нужно прото поменять все обычные строки на unicod-ные строки.
Vi2>>У тебя вместо указателей описАны структуры. Vi2>>Ребята! Вместо того чтобы ставить 0 отметили бы где ошибка — и вопрос м.б. был бы решён.
M>Сделал указатели. Все равно та же хрень. M>Есть мысль насчет того что в StartupInfoW должен передаваться указатель на desktop и windowstation для того юзера которого мы логиним. А он у меня nil перед вызовом функции CreateProcessWithLogonW. Как сказано в MSDN, в статье M>INFO: CreateProcessAsUser, Windowstations and Desktops :
M>When a process is launched via the CreateProcessAsUser API, the process will be launched into a windowstation and desktop combination based on the value of lpDesktop in the STARTUPINFO structure parameter. If a windowstation and desktop combination is specified in the lpDesktop member, the system will attempt to launch the process into that windowstation and desktop. If the lpDesktop member is initialized to NULL, the system will attempt to use the same windowstation and desktop as the calling process. If it is initialized with the empty string, "", the system will either create a new invisible windowstation and desktop or if one has been created via a prior call using the same access token, the existing windowstation and desktop will be used.
M>Так что мысль такая — надо как и вслучае использования CreateProcessAsUser давать доступ юзеру к десктопу и виндоустэйшну (получим указатель) и передавать его в структуру PStartupInfoW перед вызовом CreateProcessWithLogonW. Или CreateProcessWithLogonW сама должна все сделать?
M>Кто, что думает по этому поводу?
Я не думаю, я пробую
Если из под админа попытаться запустить обычного юзера, функция вернёт TRUE, но созданное приложение не запустится, выскочит исключение — ты бы не пропустил этот момент.
Админ из под админа запускается.
Если в четвёртом параметре передать не LOGON_WITH_PROFILE (1), а LOGON_NETCREDENTIALS_ONLY (2), то ситуация похожа на то, что ты описываешь:
— функция GetUserName из запушенного приложения всегда возвращает моё имя
— приложение запускается не зависимо от содержимого параметров lpUsername, lpDomain и lpPassword.
Если кто-нибудь объяснит мне, в чём смысл этого режима, буду сильно благодарен.
Делай что должно, и будь что будет
Re[6]: Как запустить программу от имени пользователя
SH>>2. В правильном прототипе не STARTUPINFOA, а STARTUPINFOW
ZZ>Знаю, но STARTUPINFOW в Windows.pas нету :(( А самому описывать было лень... Но — SizeOf(STARTUPINFOA)=SizeOf(STARTUPINFOW) Или нет?? А в самих параметрах нет ни одной строки (ни ANSI ни Unicode) => разницы нет.
Вот и я поэтому спросил — чем отличаются эти структуры?! В STARTUPINFOW нет никаких строк.
Re[6]: Как запустить программу от имени пользователя
Здравствуйте ZZ, Вы писали:
ZZ>По моему, const и var — Это и есть "указатели"
про const не знал, спасибо.
SH>>2. В правильном прототипе не STARTUPINFOA, а STARTUPINFOW
ZZ>Знаю, но STARTUPINFOW в Windows.pas нету ( А самому описывать было лень... Но — SizeOf(STARTUPINFOA)=SizeOf(STARTUPINFOW) Или нет?? А в самих параметрах нет ни одной строки (ни ANSI ни Unicode) => разницы нет.
Ну да, действительно.
SH>>3. В параметр lpCommandLine нельзя передавать константную строку. http://msdn.microsoft.com/library/en-us/dllproc/prothred_2gl3.asp — описание CreateProcessWithLogonW,
SH>>lpCommandLine SH>>[in] Pointer to a null-terminated string that specifies the command line to execute. SH>>This function will fail if this parameter is a const string.
SH>>ты передаёшь 'cmd.exe'. Возможно, delphi размещает такие строки в куче (или ещё где-то), но сомневаюсь. ZZ>А вот черт его знает, но поверь наслово — работает
У меня тоже работает. Странно. Помню CreateProcessW у меня падала, когда я ей константу передовал.
ZZ>(если очень хочешь, могу выслать ехе, хотя врядли ты рискнешь его запустить
Да я доверчивый... Но не надо, я и сам попробовал.
Ещё раз извиняюсь за первоночальные сомнения в твоей профессиональности.
Делай что должно, и будь что будет
Re[8]: Как запустить программу от имени пользователя
SH>Это странно. Неужели delphi не поддерживает unicode? Но в любом случае они почти обинаковы, нужно прото поменять все обычные строки на unicod-ные строки.
Конечно поддерживает. Однако в windows.pas такой структуры нет.
Кроме того в STARTUPINFOА нет никаких строк, что бы они были в UNICODE. Спращивается нахрена она вообще такая нужна — вполне хватит и STARTUPINFOA?
M>>Так что мысль такая — надо как и вслучае использования CreateProcessAsUser давать доступ юзеру к десктопу и виндоустэйшну (получим указатель) и передавать его в структуру PStartupInfoW перед вызовом CreateProcessWithLogonW. Или CreateProcessWithLogonW сама должна все сделать? SH>Я не думаю, я пробую :)
Я тоже! Щас пробую реализовать свою мысль — вручную проделать добавление пользователя к десктопу и винстэйшну, а потом эти указатели передать в STARTUPINFOA. Пока не получается.
SH>Если из под админа попытаться запустить обычного юзера, функция вернёт TRUE, но созданное приложение не запустится, выскочит исключение — ты бы не пропустил этот момент.
Вот потому я и думаю, что CreateProcessWithLogonW не выполняет все "добавки" автоматически.
SH>Админ из под админа запускается.
SH>Если в четвёртом параметре передать не LOGON_WITH_PROFILE (1), а LOGON_NETCREDENTIALS_ONLY (2), то ситуация похожа на то, что ты описываешь: SH>- функция GetUserName из запушенного приложения всегда возвращает моё имя SH>- приложение запускается не зависимо от содержимого параметров lpUsername, lpDomain и lpPassword.
Ага! Точно. У меня именно этот параметр установлен.
Такой вопрос. А если указывать LOGON_WITH_PROFILE , надо еще делать LoadUserProfile, да?
SH>Если кто-нибудь объяснит мне, в чём смысл этого режима, буду сильно благодарен.
Аналогично.
Re[9]: Как запустить программу от имени пользователя
Здравствуйте Maxus, Вы писали:
M>Ага! Точно. У меня именно этот параметр установлен. M>Такой вопрос. А если указывать LOGON_WITH_PROFILE , надо еще делать LoadUserProfile, да?
Я не делал — всё работало. В Win 2000 Pro.
Делай что должно, и будь что будет
Re[6]: Как запустить программу от имени пользователя
ZZ>>>Чисто практически.
ZZ>Знаю, но STARTUPINFOW в Windows.pas нету ( А самому описывать было лень... Но — SizeOf(STARTUPINFOA)=SizeOf(STARTUPINFOW) Или нет?? А в самих параметрах нет ни одной строки (ни ANSI ни Unicode) => разницы нет.
Так что разницы нет — весьма условное выражение, верное только если туда nil отдавать.
А вот когда будет вызываться RtlCreateProcessParameters — там уже это не все равно будет, и отлавливание такой ошибки — очень нетривиальный процесс.
sizeof действительно одинаковый, с чего ему разным быть.
А про STARTUPINFO полемика началась, после того как компилер стал ругаться, а в самом начале было неверное описание функции.
Разумеется, последние параметры не при чем, если бы они передавались структурой, была бы ошибка стека какая-нибудь, вплоть до Access Violation. То есть трабла-то в начале была, а именно, если имя юзера nil — запускается под текущим. А там и было nil, первый-то символ для UNICODE тут нулевой.
ВСЕМ СПАСИБО!!!
ВСЕ РАБОТАЕТ. Не знаю как, но работает.
SH>Админ из под админа запускается.
Поставил LOGON_WITH_PROFILE. Действительно — Админ из под Админа запускается. Попробовал Юзера — говорит "неправильное имя или пароль". Взял удалил пользователя и завел снова. ЗАРАБОТАЛО!!
Хрен знает почему.
Еще раз всем спасибо за мнения и помощь.
Кстати все обошлось — не надо указывать структуру STARTUPINFOW, хватило и STARTUPINFOA.
Здравствуйте Maxus, Вы писали:
M>Конечно поддерживает. Однако в windows.pas такой структуры нет. M>Кроме того в STARTUPINFOА нет никаких строк, что бы они были в UNICODE. Спращивается нахрена она вообще такая нужна — вполне хватит и STARTUPINFOA?
Ведь идёт о WINAPI функции CreateProcessWithLogonW, у неё нет CreateProcessWithLogonA варианта. Т.е. от тебя не зависит, работаешь ты там ANSI или UNICODE, — ты обязан передать UNICODE.
Здравствуйте vasketsov, Вы писали:
V>Здравствуйте ZZ, Вы писали:
ZZ>>>>Чисто практически.
ZZ>>Знаю, но STARTUPINFOW в Windows.pas нету ( А самому описывать было лень... Но — SizeOf(STARTUPINFOA)=SizeOf(STARTUPINFOW) Или нет?? А в самих параметрах нет ни одной строки (ни ANSI ни Unicode) => разницы нет.
V>typedef struct _STARTUPINFO { V> DWORD cb; V> LPTSTR lpReserved; V> LPTSTR lpDesktop; V> LPTSTR lpTitle;
V>} STARTUPINFO, *LPSTARTUPINFO;
V>Так что разницы нет — весьма условное выражение, верное только если туда nil отдавать. V>А вот когда будет вызываться RtlCreateProcessParameters — там уже это не все равно будет, и отлавливание такой ошибки — очень нетривиальный процесс. V>sizeof действительно одинаковый, с чего ему разным быть.
Меня не совсем правильно поняли — Там стояло ZeroMemory() и ничего кроме cb не заполнено и нет ни одной строки => разницы между A и W нет никакой. Если очень надо что-что изменить — пожалуйста переписывай STARTUPINFOW (напомню — в дельфе его вроде как нет).
Ну не буду вам мешать вести интересную полемику продолжайте пожалуйста....