Interactive Сервис, с Log on : [сетевой юзер]
От: -lexa- Россия  
Дата: 06.03.02 12:00
Оценка:
Проблема в следующем :

Win2k, есть сервис , содержащий DCom объекты , соответственно чтоб их использовать по сети в Log on стоит не LocalSystem и данный сервис запускается в неинтерактивной сессии(window station). В то же время один из методов объекта должен выдавать юзеру диалог.
Соответственно необходимо обеспечить возможность взаимодействия сервиса с активным(видимым) десктопом из неинтерактивной сессии. В MSDN написано что для этого необходимо инперсонализоваться открыть интерактивную сессию, в ней выдать диалог , вернуться в исхлдную сессию... Там приведен код с инперсонализацией через RpcImpersonateClient(h) , где необходимый handle h передается в метод. У меня этого хендела на клиенте нет тк я в явном виде rpc не использую. Как выйти из ситуации — может кто сталкивался с проблеммой — киньте example

ps
пробовал инперсонализовываться через CoImpersonateClient в коде соответствующего метода Com объекта — не отрабатывает

вот код с использованием CoImpersonateClient

STDMETHODIMP CServiceComObj::ShowMyDlg2()
{

DWORD dwThreadId;
HWINSTA hwinstaSave;
HDESK hdeskSave;
HWINSTA hwinstaUser;
HDESK hdeskUser;
int result;

// Ensure connection to service window station and desktop, and
// save their handles.

GetDesktopWindow();
hwinstaSave = GetProcessWindowStation();
dwThreadId = GetCurrentThreadId();
hdeskSave = GetThreadDesktop(dwThreadId);

// Impersonate the client and connect to the User's
// window station and desktop.

// RpcImpersonateClient(h);
LPSTR lpszWindowStation="WinSta0";
LPSTR lpszDesktop="WinSta0\\Default";
LPSTR lpszText="Данный MessageBox вызывается из сервиса \n со сменой Window Station на интерактивную \n и инперсонализацией процесса сервиса7";
LPSTR lpszTitle="Сообщение о кошках";
UINT fuStyle=MB_OK;

HRESULT hrInpersonate;

hrInpersonate=CoImpersonateClient( );

hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
if (hwinstaUser == NULL)
{
CoRevertToSelf();
return S_OK;
}

SetProcessWindowStation(hwinstaUser);
hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
if (hdeskUser == NULL)
{
SetProcessWindowStation(hwinstaSave);
CloseWindowStation(hwinstaUser);
return S_OK;
}
SetThreadDesktop(hdeskUser);

dwGuiThreadId = dwThreadId;
result = MessageBox(NULL, lpszText, lpszTitle, fuStyle);
// MessageBox выдается для простоты в данном примере — на самом деле здесь свой диатог так что
//MB_DEFAULT_DESKTOP_ONLY не подходит...
dwGuiThreadId = 0;

SetThreadDesktop(hdeskSave);
SetProcessWindowStation(hwinstaSave);
CloseDesktop(hdeskUser);
CloseWindowStation(hwinstaUser);

return S_OK;
}
-А где же товарищи Кошки?
-Они не приехали....
Re: Interactive Сервис, с Log on : [сетевой юзер]
От: Alex Fedotov США  
Дата: 06.03.02 18:37
Оценка:
Здравствуйте -lexa-, Вы писали:

L>Win2k, есть сервис , содержащий DCom объекты , соответственно чтоб их использовать по сети в Log on стоит не LocalSystem и данный сервис запускается в неинтерактивной сессии(window station). В то же время один из методов объекта должен выдавать юзеру диалог.


А если в этот момент нет интерактивного пользователя? А если их несколько, подключенных через через Terminal services? Уж сколько раз твердили миру, не дело показывать UI из сервера...

Но если очень хочется:

1. Зарегистрируй сервис как интерактивный (SERVICE_INTERACTIVE_PROCESS), или

2. Скачай http://www.alexfedotov.com/samples/svcui.zip и посмотри как устроена функция ThreadInteract. Вызов MessageBox замени на свой диалог.
-- Alex Fedotov
Re[2]: Interactive Сервис, с Log on : [сетевой юзер]
От: -lexa- Россия  
Дата: 12.03.02 23:56
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Здравствуйте -lexa-, Вы писали:




AF>А если в этот момент нет интерактивного пользователя? А если их несколько, подключенных через через Terminal services? Уж сколько раз твердили миру, не дело показывать UI из сервера...


На счет интерактивного пользователя — он точно есть в этот момент. Просто в силу уже реализованного до меня один и тот же сервис используется как DCOM сервер и сервис в обычном понимании. Той части которая работает с GUI юзер в Logon не нужен — достаточно LocalSytem а для корректной работы DCOM в Log on Local System использоваться не может ... если не включать на компе сервере NULL сессии что может пагубно как я понял отразиться на безопасности...


AF>1. Зарегистрируй сервис как интерактивный (SERVICE_INTERACTIVE_PROCESS)


данное возможно по моим данным только при работе с Logon LocalSystem т.е. данный флаг при регистрации образно говоря выставляет соответствующую галочку в свойствах сервиса


AF>2. Скачай http://www.alexfedotov.com/samples/svcui.zip и посмотри как устроена функция ThreadInteract. Вызов MessageBox замени на свой диалог.


Пример скачал... код метода ThreadInteract очень похож на мой неработающий и на тот что я находил в MSDN....
В Вашем коде на сколько я понял полностью отсутствует код связанный с инперсонализацией... поэтому вероятно данный пример не работает с юзерами в Log on отличными от LocalHost.

Меня же интересовали именно механизмы инперсонализации....

Тем не менее я перекопировал Ваш метод в cpp класса моего сервиса. Класс создан визардом VC как ATL COM App Wisard-> реализация сервера как service

вызов метода ThreadInteract поместил в CServiceModule::Run()
после SetServiceStatus(SERVICE_RUNNING);
на сколько я понимаю место вызов аналогично Вашему

тем не менее не отрабатывает ThreadInteract при SetThreadDesktop(hdesk) с кодом ошибки 170 — Требуемый ресурс занят....


Не могли бы Вы выссказать свое мнение и на сей счет.... Спасибо


void CServiceModule::Run()
{
_Module.dwThreadID = GetCurrentThreadId();

HRESULT hr = CoInitialize(NULL);

_ASSERTE(SUCCEEDED(hr));

CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hr));

hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));

LogEvent(_T("Service started"));
if (m_bService)
{
SetServiceStatus(SERVICE_RUNNING);
ThreadInteract();
}

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);

_Module.RevokeClassObjects();

CoUninitialize();
}
поместил в
-А где же товарищи Кошки?
-Они не приехали....
Re[3]: Interactive Сервис, с Log on : [сетевой юзер]
От: Alex Fedotov США  
Дата: 13.03.02 01:58
Оценка:
Здравствуйте -lexa-, Вы писали:

AF>>А если в этот момент нет интерактивного пользователя? А если их несколько, подключенных через через Terminal services? Уж сколько раз твердили миру, не дело показывать UI из сервера...


L>На счет интерактивного пользователя — он точно есть в этот момент. Просто в силу уже реализованного до меня один и тот же сервис используется как DCOM сервер и сервис в обычном понимании.


Значит, пришло время их разделить.

L>Той части которая работает с GUI юзер в Logon не нужен — достаточно LocalSytem а для корректной работы DCOM в Log on Local System использоваться не может ... если не включать на компе сервере NULL сессии что может пагубно как я понял отразиться на безопасности...


Честно говоря, ничего не понял из выше сказанного. DCOM сам по себе прекрасно работает в LocalSystem и NULL сессии тут не при чем. Похоже, вы из сервиса пытаетесь обращаться к сетевым ресурсам, тогда действительно, из LocalSystem это работать не будет.

AF>>1. Зарегистрируй сервис как интерактивный (SERVICE_INTERACTIVE_PROCESS)


L>данное возможно по моим данным только при работе с Logon LocalSystem т.е. данный флаг при регистрации образно говоря выставляет соответствующую галочку в свойствах сервиса


Естественно.

AF>>2. Скачай http://www.alexfedotov.com/samples/svcui.zip и посмотри как устроена функция ThreadInteract. Вызов MessageBox замени на свой диалог.


L>Пример скачал... код метода ThreadInteract очень похож на мой неработающий и на тот что я находил в MSDN....

L>В Вашем коде на сколько я понял полностью отсутствует код связанный с инперсонализацией... поэтому вероятно данный пример не работает с юзерами в Log on отличными от LocalHost.

Этот метод тоже будет работать только в LocalSystem. Фактически, чтобы показать UI сервис должен выполняться в LocalSystem или в контексте интерактивного пользователя, в противном случае у него просто нет необходимых прав доступа к рабочему столу интерактивного пользователя.

L>Меня же интересовали именно механизмы инперсонализации....


Да, есть такой способ. Подразумевается, что какая-то программа, выполняющаяся в контексте интерактивного пользователя, вызывает сервис, используя named pipes, RPC или COM. Обрабатывая этот вызов, сервис имперсонирует клиента и таким образом получает доступ к рабочему столу. Но вызов должен исходить от интерактивного пользователя, что, насколько я понимаю, в ваших экспериментах было не так.
-- Alex Fedotov
Re[4]: Interactive Сервис, с Log on : [сетевой юзер]
От: -lexa- Россия  
Дата: 13.03.02 08:20
Оценка:
AF>Честно говоря, ничего не понял из выше сказанного. DCOM сам по себе прекрасно работает в LocalSystem и NULL сессии тут не при чем. Похоже, вы из сервиса пытаетесь обращаться к сетевым ресурсам, тогда действительно, из LocalSystem это работать не будет.

Вероятно я чегото глобально не понимаю — вот цитата из MSDN:

Q158508

Q5 Are there any issues with running COM servers under the system account?

A. Localsystem is a very privileged account locally, so you shouldn't run any shareware applications there. However, it has no network privileges and cannot leave the machine via any NT-secured mechanism, including file system, named pipes, DCOM, or secure RPC.

Из последнего я понял что Сервис под Localsystem нельзя использовать как DCOM сервер как раз из за ограничения прав на сетевые рресурсы ....
То есть при этом на локальной машине компоненту создавать и использовать будет можно а по сети нет....

или я не так понял.... или это не про windows 2000
-А где же товарищи Кошки?
-Они не приехали....
Re[5]: Interactive Сервис, с Log on : [сетевой юзер]
От: Alex Fedotov США  
Дата: 13.03.02 15:13
Оценка:
Здравствуйте -lexa-, Вы писали:

AF>>Честно говоря, ничего не понял из выше сказанного. DCOM сам по себе прекрасно работает в LocalSystem и NULL сессии тут не при чем. Похоже, вы из сервиса пытаетесь обращаться к сетевым ресурсам, тогда действительно, из LocalSystem это работать не будет.


L>Вероятно я чегото глобально не понимаю — вот цитата из MSDN:


L>Q158508


L>Q5 Are there any issues with running COM servers under the system account?


L>A. Localsystem is a very privileged account locally, so you shouldn't run any shareware applications there. However, it has no network privileges and cannot leave the machine via any NT-secured mechanism, including file system, named pipes, DCOM, or secure RPC.


L>Из последнего я понял что Сервис под Localsystem нельзя использовать как DCOM сервер как раз из за ограничения прав на сетевые рресурсы ....

L>То есть при этом на локальной машине компоненту создавать и использовать будет можно а по сети нет....

L>или я не так понял.... или это не про windows 2000


Ты не так понял. Здесь написано, что сервис не может быть DCOM клиентом, т.е. не сможет создавать компоненты на других машинах, так как не сможет себя аутентифицировать.
-- Alex Fedotov
Re[6]: Interactive Сервис, с Log on : [сетевой юзер]
От: -lexa- Россия  
Дата: 14.03.02 10:36
Оценка:
Здравствуйте Alex Fedotov, Вы писали:


AF>Ты не так понял. Здесь написано, что сервис не может быть DCOM клиентом, т.е. не сможет создавать компоненты на других машинах, так как не сможет себя аутентифицировать.


Возможно ....

вопрос ушел в сторону от API но тем не менее...


но я создал тестовый DCOM клиент и сервер , сервер есть сервис.

При запуск клиента на той же машине что и сервер
с галкой interact with desktop все отрабатывает.

Когда я в Logon as у сервиса сервера ставлю Localsystem то по при запуске клиента на другой машине методы не отрабатывают. Причем
HRESULT hr=::CoCreateInstance(CLSID_ServiceComObj,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER |CLSCTX_LOCAL_SERVER ,IID_IServiceComObj,(void**) &pCP );

SUCCEEDED(hr) есть true

При Logon as <Сетевой юзер с правами на машине сервера>
отрабатывает только alertService ,точнее скорее всего отрабатывают оба
при вызове метода alert клиент подвисает до остановки сервиса сервера. Данное скорее всего происходит потому что сервер создал модальный диалог на невидимом десктопе и ждет пока я на невидимом десктопе нажму в диалоге ОК что не возможно.

Вот код серверной стороны:

STDMETHODIMP CServiceComObj::alert(BSTR bsHeader, BSTR bsBody)
{
USES_CONVERSION;
MessageBoxA(NULL,OLE2A(bsBody),OLE2A(bsHeader),MB_OK);
return S_OK;
}

STDMETHODIMP CServiceComObj::alertService(BSTR bsHeader, BSTR bsBody)
{
USES_CONVERSION;
MessageBoxA(NULL,OLE2A(bsBody),OLE2A(bsHeader),MB_OK | MB_DEFAULT_DESKTOP_ONLY);
return S_OK;
}

Вот код клиентской стороны
void CClientDlg::OnButton2()
{
CComBSTR CB1=CComBSTR(OLESTR("Контент Service Alert") );
CComBSTR CB2=CComBSTR(OLESTR("Заголовок Service Alert") );

CoInitialize(NULL);
CComPtr<IServiceComObj> pCP;
HRESULT hr=::CoCreateInstance(CLSID_ServiceComObj,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER |CLSCTX_LOCAL_SERVER ,IID_IServiceComObj,(void**) &pCP );
if (SUCCEEDED(hr))
{
pCP->alertService(CB1,CB2);
}
else
{
::MessageBox(NULL,"Cant create", "Info", MB_OK);
}
CoUninitialize();
}

Вот как я делаю настройки
сервер:
ProbService -service
далее в DcomCnfg во вкладке security для ProbService делаю Use Custom ... и для всех трех RadioGroup и разрешаю группе EveryOne FullControl и Allow во всех трех RadioGroup

далее в свойствах ProbService в контрольной панели меняю юзеров в Logon as если необходимо.

клиент:
копирую серверное приложение на клиента
запускаю ProbService /RegServer

далее в DcomCnfg изменяю Run application on comp: <Комп сервера>
-А где же товарищи Кошки?
-Они не приехали....
Re[3]: Interactive Сервис, с Log on : [сетевой юзер]
От: Игорь Вартанов Ниоткуда  
Дата: 16.03.02 09:45
Оценка:
Здравствуйте -lexa-, Вы писали:

L>тем не менее не отрабатывает ThreadInteract при SetThreadDesktop(hdesk) с кодом ошибки 170 — Требуемый ресурс занят....


Чтобы SetThreadDesktop отработала правильно, необходимо соблюсти условие — до ее вызова в данном потоке не должно быть создано ни одного окна.

Следовательно, нужно пустить еще один поток, и в нем уже играться с десктопами.
---
С уважением,
Игорь
Re[4]: Interactive Сервис, с Log on : [сетевой юзер]
От: -lexa- Россия  
Дата: 17.03.02 21:27
Оценка:
Здравствуйте Игорь Вартанов, Вы писали:

ИВ>Здравствуйте -lexa-, Вы писали:




ИВ>Чтобы SetThreadDesktop отработала правильно, необходимо соблюсти условие — до ее вызова в данном потоке не должно быть создано ни одного окна.


ИВ>Следовательно, нужно пустить еще один поток, и в нем уже играться с десктопами.


Спасибо я попробую ....
хотя странно у меня же сервис .... какие окна ..... я их не создавал или они все таки есть ?
-А где же товарищи Кошки?
-Они не приехали....
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.