枚举Windows中的命名管道

Mik*_*der 4 named-pipes

我无法连接到命名管道(在这种情况下为快速cgi命名管道),根据MSDN,我应该使用CreateFile()或CallNamedPipe()(平面C API,同步-没有重叠的I / O) http:/ /msdn.microsoft.com/zh-CN/library/aa363858(VS.85).aspx

但是我得到了INVALID_HANDLE_VALUE,当我GetLastError()时它为零!

我也想知道是否可以用枚举所有命名管道某种调用,然后解析出我正在寻找的那个:“ \。\ pipe \ FastCGI \”

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

Gra*_*ers 5

问题出在这里:


    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);   
    }   
Run Code Online (Sandbox Code Playgroud)

在“ while(1)”之后,您检查Next EntryOffset == 0是否表示最后一个条目从未被报告,请移动“ if(...)break;”。到“ wprintf(...)”调用之后,您应该能够枚举所有管道。

编辑
对于那些想要完整源代码(不需要DDK)的人,这里是。请注意,这不是我的代码,可以在这里找到。此代码与原始代码之间的唯一变化是上述错误修复。

编辑v2.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: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);   
}   


Mik*_*der 1

使用未记录的函数:

// NtQueryDirectoryFile(
// IN HANDLE 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 Reset // 重新开始搜索
// );