4

我正在 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(拒绝访问。)。

因此,如果您告诉如何在 Vista 中的服务和应用程序之间进行 IPC,将会非常有帮助

提前致谢

纳瓦尼思

4

5 回答 5

3

服务和应用程序是作为具有不同完整性级别的同一用户运行,还是作为不同用户运行?

如果是前者,那么 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);
于 2008-09-22T09:41:47.037 回答
1

我注意到您正在“全局”命名空间中创建对象,但试图在本地命名空间中打开它。在公开通话中的名称中添加“Global\”是否有帮助?

此外,在 //error 区域中,是否有任何内容可以让您知道它没有被创建?

于 2008-09-22T10:16:02.647 回答
0

首先,重要的是从概念上理解需要什么。一旦理解了这一点,我们就可以从那里得到它。

在服务器上,它应该类似于:

{
   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 之前,让服务器作为简单的应用程序运行。这将消除任何与安全相关的问题。
于 2008-09-22T10:05:25.357 回答
0

“1800 INFORMATION”是对的——这是一个UIPI问题;无论如何不要在新代码中使用事件,如果在触发事件时目标阻塞事件恰好在用户模式 ​​APC 代码中,则事件信号可能会丢失。Win32 中编写服务/应用程序的规范方法是使用 RPC 调用来跨越 UIPI 边界。

于 2008-09-24T05:08:47.910 回答
0

@纳瓦尼思:

优秀的反馈。由于您的错误是拒绝访问,因此我会将所需的访问权限从您真正不需要的 EVENT_ALL_ACCESS 更改为

(SYNCHRONIZE | EVENT_MODIFY_STATE)

SYNCHRONIZE 让您等待事件,而 EVENT_MODIFY_STATE 让您调用 SetEvent、ResetEvent 和 PulseEvent。

您可能需要更多访问权限,但这是非常不寻常的。

于 2008-09-23T14:33:17.140 回答