2009-01-26 97 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系統中完成)。