問題就出在這裏:後剛「而(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);
}
你仍然需要逃避反斜槓。演示是用C編寫的,它也逃脫了它們。 – Kevin 2009-01-27 13:32:15
正確。我使用C是因爲它是事實上的語言,但我使用另一種語言來實現,不需要轉義反斜槓。 – 2009-02-18 17:46:29