Vista 上的 IPC(服务和应用程序)

发布于 2024-07-05 10:00:17 字数 1175 浏览 9 评论 0 原文

我正在 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,将会非常有帮助

提前感谢

Navaneeth

I am creating an appcation on Vista,which include a service and a Console application .Both running in same user account

In service i am creating an event and waits for that event.In console application i am opening the same event (problem starts here) and calling SetEvent function. I can not open the event (getting error 5,Access is denied) in the console application.I searched in the net and saw something about integrity level (I am not sure that the problem is related to integrity level).Its telling that service and applicaation got differnt integrity levels.

here is the part of the code,where IPC occures

service

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
}
}

Console Application

Here in application ,opening the event and seting the event

unsigned int
event_notification()
{
HANDLE ghRequestEvent = NULL ;



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

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

I am running both application (serivce and console application) with administrative privilege (i logged in as Administraor and running the console application by right clicking and using the option "run as administrator") .

The error i am getting in console application (where i am opening the event) is error no 5(Access is denied. ) .

So it will be very helpfull if you tell how to do the IPC between a service and an application in Vista

Thanks in advance

Navaneeth

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

灰色世界里的红玫瑰 2024-07-12 10:00:17

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

如果是前者,那么 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);

Are the service and the application running as the same user with different integrity levels, or are they running as different users?

If it is the former, then this article from MSDN which talks about integrity levels might help. They have some sample code for lowering the integrity level of a file. I'm not sure that this could be relevant for an event though.

#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);
  }
}

If it is the latter you might look at this link which suggests creating a NULL ACL and associating it with the object (in the example it is a named pipe, but the approach is similar for an event I'm sure:

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);
独木成林 2024-07-12 10:00:17

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

另外,在 //error 区域中,有什么东西可以让您知道它没有创建吗?

I notice that you are creating the object in the "Global" namespace but are trying to open it in a local namespace. Does adding "Global\" to the name in the open call help?

Also, in the //error area, is there anything there to let you know it wasn't created?

情话难免假 2024-07-12 10:00:17

首先,从概念上理解需要什么很重要。 一旦理解了这一点,我们就可以从那里开始。

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

{
   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 之前,让服务器作为简单应用程序运行。 这将消除任何与安全相关的问题。

First, it is important to conceptually understand what is required. Once that is understood we can take it from there.

On the server, it should look something similar to:

{
   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 */
   }
}

On the client:

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

Several points to note:

  • ResetEvent should be as early as possible, right after WaitForSingleObject or WaitForMultipleObjects. If multiple clients are using the server and first client's processing takes time, second client might set the event and it might not be caught while server processes the first request.
  • You should implement some mechanism that would notify the client that server finished processing.
  • Before doing any win32 service mumbo-jumbo, have server running as simple application. This will eliminate any security-related problems.
无畏 2024-07-12 10:00:17

@Navaneeth:

非常好的反馈。 由于您的错误是访问被拒绝,那么我会将所需的访问权限从您实际上不需要的 EVENT_ALL_ACCESS 更改为

(SYNCHRONIZE | EVENT_MODIFY_STATE)

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

您可能需要更多访问权限,但这种情况极不寻常。

@Navaneeth:

Excellent feedback. Since your error is Access Denied, then I would change the desired access from EVENT_ALL_ACCESS, which you really don't need, to

(SYNCHRONIZE | EVENT_MODIFY_STATE)

SYNCHRONIZE lets you wait on the event and EVENT_MODIFY_STATE lets you call SetEvent, ResetEvent and PulseEvent.

It is possible that you might need more access, but that is highly unusual.

几味少女 2024-07-12 10:00:17

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

"1800 INFORMATION" is right - this is a UIPI issue; don't use Events in new code anyways, the event signal can be lost if the target blocking on the event happens to be in user-mode APC code when it is fired. The canonical way in Win32 to write a service/application is to use RPC calls to cross the UIPI boundary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文