5

名前付きパイプ (この場合は高速な cgi 名前付きパイプ) への接続に問題があります。MSDN によると、CreateFile() または CallNamedPipe() を使用する必要があります (フラット C API、同期 - オーバーラップ I/O なし) http:/ /msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

それでも、INVALID_HANDLE_VALUE を取得していますが、GetLastError() を実行するとゼロになります!?

また、すべての名前付きパイプを . で列挙できるかどうかも疑問に思っています。何らかの呼び出しを行い、探しているものを解析します: "\.\pipe\FastCGI\"

そして、誰もがこれらのコメントの経験を持っていますか: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/225878

4

7 に答える 7

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

「while(1)」の直後に、Next EntryOffset == 0 かどうかを確認します。これは、最後のエントリが報告されないことを意味し、「if(...) break;」を移動します。「wprintf(...)」呼び出しの後にすると、すべてのパイプを列挙できるはずです。

EDIT
完全なソース コード (DDK を必要としない) が必要な方は、こちらをご覧ください。これは私のコードではなく、ここで見つかったことに注意してください。このコードと元のコードの唯一の変更点は、上記で説明したバグ修正です。

編集 v2.0
以下のコードに別のバグが見つかりました。反復処理中の現在の項目に関する情報を出力するときに、名前の末尾にヌル文字を配置します。このヌル文字は、実際には次のエントリの最初の 2 バイトを上書きします。これは、そのエントリの 'NextEntryOffset' 変数の最下位 2 バイトを上書きするだけです (通常は結果として 0 になります)。各「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);   
}   

于 2009-02-19T06:45:51.523 に答える
4

これを実行できるコンパイル済みツールが必要な場合は、SysInternals(Microsoftが所有)の「PipeList」を参照してください。

ここからダウンロード

于 2009-02-24T20:00:11.527 に答える
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, // 各呼び出しは 1 つのファイルのみの情報を返す
// IN PUNICODE_STRING FileTemplate OPTIONAL, // 検索用のテンプレート
// IN BOOLEAN リセット // 検索を再開
// );

于 2009-01-27T08:41:01.440 に答える
1

パイプ名を適切にエスケープしていますか? 次のようになります。\\\\.\\pipe\\FastCGI

詳細については、名前付きパイプ クライアントのデモを参照してください。

于 2009-01-27T00:15:38.030 に答える
0

わかりました。パイプリストの生成に使用されているコードに別のバグが見つかりました(最初のバグに関する投稿の詳細)。

「そして誰もがこれらのコメントを経験したことがある」に続くリンクの情報に関しては、私は彼らが話していることを理解しています、あなたが理解していないことや興味があることについてもう少し具体的に教えてください(非ブロッキング操作を実行できないことは、UNIXシステムの「従来の」方法では実行されませんが、少し嘘です)。

于 2009-02-26T13:00:31.067 に答える
0

それをキャッチしていただきありがとうございます。私はこのコードを別のCのような言語に変換し、名前だけを探しているのでFILE_NAMES_INFORMATIONを使用しました。

次に、別のアプリケーションで名前付きパイプを作成しました。

 \\.\pipe\test
于 2009-02-19T20:55:26.427 に答える
0

パイプ名の最初のバックスラッシュは、フォーラム ソフトウェアによって切り取られました。パイプ名は次のとおりです。

\\.\pipe\test

(テストに使用している言語ではエスケープする必要はありません)

私は 2 つのアプリケーションを作成しました。1 つはパイプ サーバー、もう 1 つはブロックをテストするためのパイプ クライアントなどで、完全に動作します。

私はパイプを作成します:

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 は返されませんが、後で使用して完全に機能する有効なハンドルは、期待どおりにブロックされ、正常に通信します。

于 2009-02-24T05:07:29.627 に答える