2009-01-26 94 views
4

我无法连接到命名管道(在这种情况下,一个快速CGI命名管道) 根据MSDN,我应该使用CreateFile()或CallNamedPipe() (flat C API,同步 - 没有重叠的I/O) http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx在Windows中枚举命名管道

然而,我得到INVALID_HANDLE_VALUE,当我GetLastError()它是零!?

我也想知道是否可以枚举所有命名管道通话某种然后解析出一个我要找: “\ \管道\ FastCGI的\”。

,并没有任何人有这些评论的经验: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/225878

回答

1

使用无证功能:

// NtQueryDirectoryFile(
//手柄文件句柄,//处理的文件
//手柄EventHandle可选,
// IN PIO_APC_ROUTINE ApcRoutine可选,
// IN PVOID ApcContext OPTIONAL,
// OUT PIO_STATUS_BLOCK IoStatusBlock,
// OUT PVOID缓冲液,//指针到缓冲器以接收结果
// IN ULONG BufferLength中,//缓冲
的长度 // IN FILE_INFORMATION_CLASS InformationClass,//信息类型
// IN BOOLEAN ReturnByOne,//每个调用返回信息仅对一个文件
// IN PUNICODE_STRING FileTemplate OPTIONAL ,//用于搜索的模板
// IN BOOLEAN重置//重启搜索
//);

+0

你仍然需要逃避反斜杠。演示是用C编写的,它也逃脱了它们。 – Kevin 2009-01-27 13:32:15

+0

正确。我使用C是因为它是事实上的语言,但我使用另一种语言来实现,不需要转义反斜杠。 – 2009-02-18 17:46:29

1

你逃脱管正确地命名?它应该看起来像:\\\\.\\pipe\\FastCGI

有关更多信息,请参阅Named Pipe Client Demo

3

问题就出在这里:后刚“而(1)”你检查下一页 EntryOffset == 0 这意味着最后一个条目永远不会被报道,移动


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

的“如果(...)突破;“在“wprintf(...)”调用之后,你应该能够枚举所有的管道。

编辑
对于那些你们谁愿意完整的源代码(无需DDK)在这儿呢。请不要说这不是我的代码,并且被发现here。此代码和原始代码之间的唯一变化是上面详细描述的错误修复。

EDIT 2.0
实测值在下面的代码另一个错误。当打印关于正在迭代的当前项目的信息时,它会在名称的末尾放置一个空字符。这个空字符实际上覆盖了下一个条目的前2个字节,它恰好覆盖了该条目中的'NextEntryOffset'变量的2个最低有效字节(通常使得它等于0),因此只有前2个条目是每个从每个'NtQueryDirectoryFile'调用枚举。

我已经为下面的代码添加了一个修复程序,它可以解决这个问题(存储WCHAR被清除,然后在打印后恢复它)。一个黑客的位,但这只是一些示例代码,避免使用wprintf来打印名称,或者将其复制到另一个可以安全地将NULL结尾的缓冲区)。


 

// 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:[email protected], 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); 
} 
 
0

感谢您轻松没收。我转换这个代码,像语言的另一个C和使用: FILE_NAMES_INFORMATION ,因为我只想找的名字

然后,我创建了一个名为管道与其他应用程序:

\\.\pipe\test 
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,但我用后来和一个有效的手柄完美地工作 他们阻止预期和交流的罚款。

3

如果你想要一个可以为你做这件事的编译工具,请查看SysInternals(Microsoft拥有)的“PipeList”。

Download Here

0

好吧,我发现代码中的另一个bug被用来生成管列表(在后大约第一个错误的详细信息)。

只要“以及有人有这些意见的经验”的链接中的信息,我明白他们在说什么,你能更具体一些你不明白或好奇的(关于不能进行非阻塞操作的部分是一个谎言顺便说一句,虽然它没有在传统的unix系统中完成)。