Enumerating named pipes in Windows

I am having problems connecting to a named pipe (in this case, the fast cgi named pipe) According to MSDN, I have to use CreateFile () or CallNamedPipe () (flat C API, synchronous - without overlapping I / O) http: // msdn. microsoft.com/en-us/library/aa363858(VS.85).aspx

But I get INVALID_HANDLE_VALUE, and when I GetLastError () is zero !?

I am also wondering if I can simply list all named pipes using. a call of some kind, and then parse the one I'm looking for: "\. \ Pipe \ FastCGI \"

and anyone has experience with these comments: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/225878

+4
source share
7 answers

Using an undocumented function:

// NtQueryDirectoryFile (
// IN HANDLE FileHandle, // process the file
// IN HANDLE EventHandle OPTIONAL,
// IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
// In the PVOID ApcContext OPTIONAL,
// OUT PIO_STATUS_BLOCK IoStatusBlock,
// OUT PVOID Buffer, // pointer to the buffer to get the result
// IN ULONG BufferLength, // buffer length
// IN FILE_INFORMATION_CLASS InformationClass, // type of information
// IN BOOLEAN ReturnByOne, // each call returns information for only one file
// IN PUNICODE_STRING FileTemplate OPTIONAL, // template for search
// IN BOOLEAN Reset // restart the search
//);

+1
source

the problem is here:

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

immediately after "while (1)" you check if EntryOffset == 0 is next . This means that the last record is never reported, move "if (...) break;" after calling "wprintf (...)" and you can list all the channels.

EDIT
For those of you who would like to get the full source code (without requiring DDK) here. Please, not that it is not my code and was found here . The only change between this code and the original is error correction, as described above.

EDIT v2.0
Found one more error in the code below. As it prints information about the current element with which it iterates, it places a null character at the end of the name. This null character actually overwrites the first 2 bytes of the next record, which simply overwrites the 2 least significant bytes of the NextEntryOffset variable in this record (this usually results in it being 0), so only the first 2 elements are listed from every call to NtQueryDirectoryFile "

I added a fix to the code below that should solve this problem (save the WCHAR that will be cleaned and then restore it after printing. Battle is hacking, but this is just sample code for the correct implementation, either do not use wprintf to print the name or copy it to another buffer, which you can safely NULL at the end).


 // 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); }
// 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); } 
+3
source

If you need a compiled tool that can do this for you, check out the "PipeList" from SysInternals (owned by Microsoft).

Download here

+3
source

Are you avoiding the pipe name correctly? It should look like this: \\\\.\\pipe\\FastCGI

For more information, see "Demo version of the client number . "

+1
source

Thanks for catching this. I converted this code to another language similar to C, and used: FILE_NAMES_INFORMATION since I am only looking for names

Then I created a named pipe with another application:

  \\.\pipe\test 
0
source

The first backslash of the pipe name was disabled by the forum software. Pipe Name:

 \\.\pipe\test 

(This should not be avoided in the language I use for testing)

I wrote two applications: one is a channel server, one is a channel client to check for blockages, etc. They work great.

I create a channel using

 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 

It does not return INVALID_HANDLE_VALUE, but a valid descriptor, which I use later and works fine. They are blocked, as expected, and communicate fine.

0
source

Well, I found another error in the code that is used to create the channel list (for details, see the first error message).

As for the information in the following link, β€œand someone has experience with these comments,” I understand what they are talking about, could you be more specific about what you don’t understand or are not interested in (the part about the inability to do non-blocking operations are a bit of a btw lie, although this is not done in the "traditional" way of unix systems).

0
source

All Articles