我无法连接到命名管道(在这种情况下是一个快速的cgi命名管道) 根据MSDN,我应该使用CreateFile()或CallNamedPipe() (flat C API,同步 - 没有重叠的I / O) http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
然而我得到了INVALID_HANDLE_VALUE,当我遇到GetLastError()时它是零!?
我也想知道我是否可以使用某种。调用枚举所有命名管道,然后解析出我正在寻找的那个: “\。\管\ FastCGI的\”
并且有没有人有这些评论的经验: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/225878
答案 0 :(得分:4)
问题出在这里:
TmpInfo = DirInfo;
while(1)
{
if(TmpInfo->NextEntryOffset==0)
break;
TmpInfo->FileDirectoryInformationClass.FileName[TmpInfo->FileNameLength/sizeof(WCHAR)] = NULL;
wprintf(L"%s (%d, %d)\n",TmpInfo->FileDirectoryInformationClass.FileName,
TmpInfo->EndOfFile.LowPart,
TmpInfo->AllocationSize.LowPart );
TmpInfo = (PFILE_QUERY_DIRECTORY)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);
}
在“while(1)”之后,检查 Next EntryOffset == 0
这意味着永远不会报告最后一个条目,移动“if(...)break;”在“wprintf(...)”调用之后,您应该能够枚举所有管道
的 EDIT
的的
对于那些想要完整源代码(不需要DDK)的人来说,就是这样。请注意,这不是我的代码,而是here。此代码与原始代码之间的唯一变化是上面详述的错误修复
编辑v2.0
在下面的代码中发现了另一个错误。当它打印有关它正在迭代的当前项的信息时,它会在名称的末尾放置一个空字符。这个空字符实际上会覆盖下一个条目的前2个字节,这恰好会覆盖该条目中'NextEntryOffset'变量的2个最低有效字节(通常会使其等于0),因此只有前2个项目是每个从每个'NtQueryDirectoryFile'调用中枚举。
我已经在下面的代码中添加了一个修复程序来解决这个问题(存储WCHAR被清除然后在打印后恢复它。有点破解,但这只是一些示例代码,为了正确实现,要么避免使用wprintf打印名称,或将其复制到另一个缓冲区,您可以安全地将其结尾为。)
// pipelist.cpp (Windows NT/2000)
//
// This example will show how you can enumerate all named pipes
// active on a system.
//
// (c)2000 Ashot Oganesyan K, SmartLine, Inc
// mailto:ashot@aha.ru, http://www.protect-me.com, http://www.codepile.com
#include <windows.h>
#include <stdio.h>
#define FileDirectoryInformation 1
#define STATUS_NO_MORE_FILES 0x80000006L
typedef struct
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct
{
LONG Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef struct {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
union {
struct {
WCHAR FileName[1];
} FileDirectoryInformationClass;
struct {
DWORD dwUknown1;
WCHAR FileName[1];
} FileFullDirectoryInformationClass;
struct {
DWORD dwUknown2;
USHORT AltFileNameLen;
WCHAR AltFileName[12];
WCHAR FileName[1];
} FileBothDirectoryInformationClass;
};
} FILE_QUERY_DIRECTORY, *PFILE_QUERY_DIRECTORY;
// ntdll!NtQueryDirectoryFile (NT specific!)
//
// The function searches a directory for a file whose name and attributes
// match those specified in the function call.
//
// NTSYSAPI
// NTSTATUS
// NTAPI
// NtQueryDirectoryFile(
// IN HANDLE FileHandle, // handle to the file
// IN HANDLE EventHandle OPTIONAL,
// IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
// IN PVOID ApcContext OPTIONAL,
// OUT PIO_STATUS_BLOCK IoStatusBlock,
// OUT PVOID Buffer, // pointer to the buffer to receive the result
// IN ULONG BufferLength, // length of Buffer
// IN FILE_INFORMATION_CLASS InformationClass,// information type
// IN BOOLEAN ReturnByOne, // each call returns info for only one file
// IN PUNICODE_STRING FileTemplate OPTIONAL, // template for search
// IN BOOLEAN Reset // restart search
// );
typedef LONG (WINAPI *PROCNTQDF)( HANDLE,HANDLE,PVOID,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,
UINT,BOOL,PUNICODE_STRING,BOOL );
PROCNTQDF NtQueryDirectoryFile;
void main(void)
{
LONG ntStatus;
IO_STATUS_BLOCK IoStatus;
HANDLE hPipe;
BOOL bReset = TRUE;
PFILE_QUERY_DIRECTORY DirInfo,
TmpInfo;
NtQueryDirectoryFile = (PROCNTQDF)GetProcAddress(
GetModuleHandle("ntdll"),
"NtQueryDirectoryFile"
);
if (!NtQueryDirectoryFile)
return;
hPipe = CreateFile("\\\\.\\Pipe\\",GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL,OPEN_EXISTING,0,NULL);
if(hPipe == INVALID_HANDLE_VALUE)
return;
DirInfo = (PFILE_QUERY_DIRECTORY) new BYTE[1024];
printf("Pipe name (Number of instances, Maximum instances)\n\n");
while(1)
{
ntStatus = NtQueryDirectoryFile(hPipe,NULL,NULL,NULL,&IoStatus,DirInfo,1024,
FileDirectoryInformation,FALSE,NULL,bReset);
if (ntStatus!=NO_ERROR)
{
if (ntStatus == STATUS_NO_MORE_FILES)
break;
return;
}
TmpInfo = DirInfo;
while(1)
{
// Store old values before we mangle the buffer
const int endStringAt = TmpInfo->FileNameLength/sizeof(WCHAR);
const WCHAR oldValue = TmpInfo->FileDirectoryInformationClass.FileName[endStringAt];
// Place a null character at the end of the string so wprintf doesn't read past the end
TmpInfo->FileDirectoryInformationClass.FileName[endStringAt] = NULL;
wprintf(L"%s (%d, %d)\n",TmpInfo->FileDirectoryInformationClass.FileName,
TmpInfo->EndOfFile.LowPart,
TmpInfo->AllocationSize.LowPart );
// Restore the buffer to its correct state
TmpInfo->FileDirectoryInformationClass.FileName[endStringAt] = oldValue;
if(TmpInfo->NextEntryOffset==0)
break;
TmpInfo = (PFILE_QUERY_DIRECTORY)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);
}
bReset = FALSE;
}
delete DirInfo;
CloseHandle(hPipe);
}
答案 1 :(得分:3)
如果您想要一个可以为您执行此操作的编译工具,请查看SysInternals(由Microsoft拥有)中的“PipeList”。
答案 2 :(得分:1)
您是否正确地逃脱了管道名称?它应该如下所示:\\\\.\\pipe\\FastCGI
有关详细信息,请参阅Named Pipe Client Demo。
答案 3 :(得分:1)
使用未记录的功能:
// NtQueryDirectoryFile(
// IN处理FileHandle,//处理文件
// IN HANDLE EventHandle OPTIONAL,
// IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
// IN PVOID ApcContext OPTIONAL,
// OUT PIO_STATUS_BLOCK IoStatusBlock,
// OUT PVOID Buffer,//指向缓冲区的指针,用于接收结果
// IN ULONG BufferLength,//缓冲区长度
// IN FILE_INFORMATION_CLASS InformationClass,//信息类型
// IN BOOLEAN ReturnByOne,//每个调用只返回一个文件的信息
// IN PUNICODE_STRING FileTemplate OPTIONAL,//搜索模板
// IN BOOLEAN重置//重新开始搜索
//);
答案 4 :(得分:0)
感谢您抓住这一点。我将此代码转换为另一种C语言并使用: FILE_NAMES_INFORMATION 因为我只是在寻找名字
然后我用另一个应用程序创建了一个命名管道:
\\.\pipe\test
答案 5 :(得分:0)
管道名称的第一个反斜杠被论坛软件切断了。管道名称是:
\\.\pipe\test
(不需要使用我用于测试的语言进行转义)
我编写了两个应用程序,一个是管道服务器,另一个是管道客户端来测试阻塞等 他们工作得很好。
我用:
创建管道Pipe_Name = "\\.\pipe\test"
MaxInstances = 1
OutBufferSize = 1024
InBufferSize = 1024
hPipe = CreateNamedPipe(_
Pipe_Name, _ ' Name of the Pipe
PIPE_ACCESS_DUPLEX, _ ' Specifies the pipe access/overlapped/write-through/security access modes
PIPE_TYPE_MESSAGE OR PIPE_READMODE_MESSAGE, _ ' Specifies the type, read, and wait modes of the pipe handle
MaxInstances, _ ' Specifies the maximum number of instances that can be created for this pipe
OutBufferSize, _ ' Specifies the number of bytes to reserve for the output buffer
InBufferSize, _ ' Specifies the number of bytes to reserve for the input buffer
0, _ ' Specifies the default time-out value, in milliseconds
Security_Declaration) ' Pointer to a SECURITY_ATTRIBUTES structure
它不会返回INVALID_HANDLE_VALUE,而是一个有效的句柄,我随后使用并完美地运行 它们按预期阻止并且沟通良好。
答案 6 :(得分:0)
好的,我在代码中发现了另一个用于生成管道列表的错误(关于第一个错误的帖子中的详细信息)。
至于以下链接中的信息“并且任何人都有这些评论的经验”,我理解他们在谈论什么,你能不能更具体地了解你不理解或不感兴趣的事情(关于不能进行非阻塞操作的部分有点谎言,尽管它不是以unix系统的“传统”方式完成的。)