Я создаю приложение в 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) ;
}
Я запускаю оба приложения (сервисное и консольное) с правами администратора (я вошел в систему как администратор и запустил консольное приложение, щелкнув правой кнопкой мыши и используя опцию «запуск от имени администратора»).
Ошибка, которую я получаю в консольном приложении (где я открываю событие), - это ошибка № 5 (доступ запрещен).
Так что будет очень полезно, если вы расскажете, как сделать IPC между службой и приложением в Vista.
заранее спасибо
Navaneeth





Служба и приложение работают от имени одного пользователя с разными уровнями целостности или от имени разных пользователей?
Если первое, то эта статья из 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);
Здесь определяется язык определения дескрипторов безопасности (SDDL) msdn.microsoft.com/en-us/library/aa379567(VS.85).aspx
Во-первых, важно концептуально понять, что требуется. Как только это будет понято, мы сможем взять это оттуда.
На сервере это должно выглядеть примерно так:
{
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);
}
Несколько замечаний:
Вам следует использовать событие автоматического сброса (второй параметр CreateEvent имеет значение false), а не беспокоиться о состоянии гонки, которое вы описываете.
Я заметил, что вы создаете объект в «глобальном» пространстве имен, но пытаетесь открыть его в локальном пространстве имен. Помогает ли добавление "Global \" к имени в открытом вызове?
Кроме того, есть ли что-нибудь в области // ошибки, чтобы вы знали, что оно не было создано?
@Navaneeth:
Отличная обратная связь. Поскольку ваша ошибка - Доступ запрещен, я бы изменил желаемый доступ с EVENT_ALL_ACCESS, который вам действительно не нужен, на
(SYNCHRONIZE | EVENT_MODIFY_STATE)
SYNCHRONIZE позволяет ждать события, а EVENT_MODIFY_STATE позволяет вызывать SetEvent, ResetEvent и PulseEvent.
Возможно, вам понадобится больше доступа, но это очень необычно.
«1800 ИНФОРМАЦИЯ» правильно - это проблема UIPI; в любом случае не используйте события в новом коде, сигнал события может быть потерян, если целевая блокировка события происходит в коде APC пользовательского режима, когда оно запускается. Канонический способ написания службы / приложения в Win32 - использовать вызовы RPC для пересечения границы UIPI.
Где можно найти описание использованной выше строки LOW_INTEGRITY_SDDL_SACL_W? Я видел это только в образце кода, но никогда не определялся официально.