最近写了一段windows下管道通信的代码,通过如下方式创建命名管道
HANDLE hPipe = CreateNamedPipe(L"////.//pipe//testspipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
0, 1, 1024, 1024, 0, NULL);
这段代码在win xp/2003上表现良好,没有什么问题,可是到了win7上运行,就出现创建管道失败的错误。开始以为是权限的问题,后来改用administrator登录运行,问题依然存在。于是反复仔细研究,怀疑问题出在CreateNamedPipe()函数最后一个参数LPSECURITY_ATTRIBUTES 的身上,在MSDN里这样描述:
If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a named pipe grant full control to the LocalSystem account, administrators, and the creator owner. They also grant read access to members of the Everyone group and the anonymous account.
(如果 lpSecurityAttributes设成NULL,命名管道获得默认(default)的安全描述符,而且其句柄不能被继承。对于命名管道的默认安全级别描述符,ACLs(Access Control Lists,访问控制列表)授予本地用户、管理员、管道创建者,完全的控制权限。他们同时也给组内的所有成员和匿名成员提供了访问权限。翻译的不好,别见笑)
这也就说明,最后一个参数设置为NULL,就可以获得默认的安全描述符(default security descriptor),并且默认安全级别的命名管道允许匿名访问。之所以在XP/2003下能够创建成功,在WIN7下创建失败,是不是由于win nt6提高安全级别,导致的变化呢?
在http://msdn.microsoft.com/zh-cn/library/aa480152.aspx#XSLTsection146121120120 上,“命名管道的强化”一项,有如下内容,写得比较晦涩:
以下服务受到影响:运行 LocalService 或 NetworkService 的服务、选择使用服务 Sid 的服务以及在命名管道上使用 RPC 请求“默认”命名管道安全描述符的服务。
选 择使用服务 Sid 的服务意味着任何第三方服务在默认情况下都不会受到影响。服务 Sid 是 Windows Vista 中的一个新功能,您必须在服务配置中设置一个 DWORD 来进行选择。开发人员选择使用服务 Sid 后,将可采用新的服务强化行为进行测试。这一变化就是这些行为中的一项。
在命名管道上使用 RPC 请求“默认”命名管道安全描述符的服务意味着,如果某些 RPC 服务器因特殊需要而指定一个自定义的安全描述符,就不会看到任何变化。以下是受影响管道的列表:
(省略)
Sid是什么,不太清楚,但是有一个很明确的就是使用默认安全描述符的会受到影响,看来CreateNamedPipe最后一个参数不能给NULL,于是将创建管道的代码改为,增加了一个自定义安全描述符:
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);
hPipe = CreateNamedPipe(L"////.//pipe//testspipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
0, 1, 1024, 1024, 0, &sa);
在到win7下测试,创建命名管道果然成功了