我无法连接到命名管道(在这种情况下为快速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
问题出在这里:
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(...)”调用之后,您应该能够枚举所有管道。
编辑
对于那些想要完整源代码(不需要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#include #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); }