IPC на Vista (сервис и приложение) - PullRequest
4 голосов
/ 22 сентября 2008

Я создаю приложение в Vista, которое включает в себя службу и консольное приложение. Оба работают под одной учетной записью пользователя

В сервисе я создаю событие и жду этого события. В консольном приложении я открываю то же событие (здесь начинается проблема) и вызываю SetEvent функцию. Я не могу открыть событие (получаю ошибку 5, доступ запрещен) в консольном приложении. Я искал в сети и увидел кое-что об уровне целостности (я не уверен, что проблема связана с уровнем целостности). Он говорит, что служба и приложение получило разные уровни целостности.

вот часть кода, где происходит IPC

сервис

DWORD
WINAPI IpcThread(LPVOID lpParam)
{
HANDLE ghRequestEvent = NULL ;

ghRequestEvent = CreateEvent(NULL, FALSE,
FALSE, "Global\\Event1") ; //creating the event

if(NULL == ghRequestEvent)
{
//error
}
while(1)
{
WaitForSingleObject(ghRequestEvent, INFINITE) //waiting for the event
//here some action related to event
}
}

Консольное приложение

Здесь, в приложении, открытие события и установка события

unsigned int
event_notification()
{
HANDLE ghRequestEvent = NULL ;



 ghRequestEvent = OpenEvent(SYNCHRONIZE|EVENT_MODIFY_STATE, FALSE, "Global\\Event1") ;

if(NULL == ghRequestEvent)
{
//error
}
SetEvent(ghRequestEvent) ;
} 

Я запускаю оба приложения (serivce и консольное приложение) с правами администратора (я вошел в систему как Администратор или запускаю консольное приложение, щелкнув правой кнопкой мыши и используя опцию «Запуск от имени администратора»).

Ошибка, которую я получаю в консольном приложении (где я открываю событие), это ошибка № 5 (доступ запрещен).

Так что будет очень полезно, если вы расскажете, как выполнить IPC между службой и приложением в Vista

Заранее спасибо

Navaneeth

Ответы [ 5 ]

3 голосов
/ 22 сентября 2008

Служба и приложение работают как один и тот же пользователь с разными уровнями целостности или они работают как разные пользователи?

Если это первое, то статья MSDN , в которой говорится об уровнях целостности, может помочь . У них есть некоторый пример кода для понижения уровня целостности файла. Я не уверен, что это может иметь отношение к событию.

#include <sddl.h>
#include <AccCtrl.h>
#include <Aclapi.h>

void SetLowLabelToFile()
{
  // The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity 
  #define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
  DWORD dwErr = ERROR_SUCCESS;
  PSECURITY_DESCRIPTOR pSD = NULL;    

  PACL pSacl = NULL; // not allocated
  BOOL fSaclPresent = FALSE;
  BOOL fSaclDefaulted = FALSE;
  LPCWSTR pwszFileName = L"Sample.txt";

  if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
         LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD;, NULL)) 
  {
    if (GetSecurityDescriptorSacl(pSD, &fSaclPresent;, &pSacl;, 
         &fSaclDefaulted;))
    {
      // Note that psidOwner, psidGroup, and pDacl are 
      // all NULL and set the new LABEL_SECURITY_INFORMATION
      dwErr = SetNamedSecurityInfoW((LPWSTR) pwszFileName, 
                 SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, 
                 NULL, NULL, NULL, pSacl);
    }
    LocalFree(pSD);
  }
}

Если это последняя, ​​вы можете посмотреть на эту ссылку, которая предлагает создать NULL ACL и связать его с объектом (в примере это именованный канал, но подход аналогичен для события Я уверен:

BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
SECURITY_ATTRIBUTES sa;

sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = &sd;

InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, (PACL) 0, FALSE);

CreateNamedPipe(..., &sa);
1 голос
/ 22 сентября 2008

Я заметил, что вы создаете объект в «глобальном» пространстве имен, но пытаетесь открыть его в локальном пространстве имен. Помогает ли добавление «Global \» к имени в открытом вызове?

Кроме того, в области // ошибок есть ли что-то, чтобы вы знали, что он не был создан?

0 голосов
/ 24 сентября 2008

«1800 ИНФОРМАЦИЯ» - это проблема UIPI; В любом случае, не используйте Events в новом коде, сигнал события может быть потерян, если целевая блокировка события происходит в коде APC пользовательского режима при его срабатывании. Канонический способ написания службы / приложения в Win32 - это использование вызовов RPC для пересечения границы UIPI.

0 голосов
/ 23 сентября 2008

@ Navaneeth:

Отличная обратная связь. Поскольку ваша ошибка - «Отказано в доступе», я бы изменил желаемый доступ с EVENT_ALL_ACCESS, который вам действительно не нужен, на

(SYNCHRONIZE | EVENT_MODIFY_STATE)

SYNCHRONIZE позволяет вам ждать события, а EVENT_MODIFY_STATE позволяет вызывать SetEvent, ResetEvent и PulseEvent.

Возможно, вам понадобится больше доступа, но это весьма необычно.

0 голосов
/ 22 сентября 2008

Во-первых, важно концептуально понять, что требуется. Как только это будет понято, мы можем взять это оттуда.

На сервере это должно выглядеть примерно так:

{
   HANDLE hEvent;
   hEvent = CreateEvent(null, true, false, TEXT("MyEvent"));
   while (1)
   {
       WaitForSingleObject (hEvent);
       ResetEvent (hEvent);
       /* Do something -- start */
       /* Processing 1 */
       /* Processing 2 */
       /* Do something -- end */
   }
}

На клиенте:

{
   HANDLE hEvent;
   hEvent = OpenEvent(0, false, TEXT("MyEvent"));
   SetEvent (hEvent);
}

Несколько замечаний:

  • ResetEvent должен быть как можно раньше, сразу после WaitForSingleObject или WaitForMultipleObjects. Если несколько клиентов используют сервер и обработка первого клиента занимает время, второй клиент может установить событие, и оно может не быть перехвачено, пока сервер обрабатывает первый запрос.
  • Вам следует внедрить некоторый механизм, который уведомит клиента о том, что сервер завершил обработку.
  • Перед выполнением любого сервиса win32 mumbo-jumbo, запустите сервер как простое приложение. Это устранит любые проблемы, связанные с безопасностью.
...