|
楼主 |
发表于 2010-7-31 16:16:55
|
显示全部楼层
- //NtQuery.cpp By 腾袭 2010-7-25
- #include "StdAfx.h"
- #include "NtQuery.h"
- HMODULE CNtQuery::m_hNtdll = NULL;
- FN_NtQueryDirectoryFile CNtQuery::fn_NtQueryDirectoryFile;
- FN_NtOpenFile CNtQuery::fn_NtOpenFile;
- FN_NtClose CNtQuery::fn_NtClose;
- FN_RtlInitUnicodeString CNtQuery::fn_RtlInitUnicodeString;
- FN_RtlInitAnsiString CNtQuery::fn_RtlInitAnsiString;
- FN_RtlAnsiStringToUnicodeString CNtQuery::fn_RtlAnsiStringToUnicodeString;
- FN_RtlUnicodeStringToAnsiString CNtQuery::fn_RtlUnicodeStringToAnsiString;
- FN_RtlFreeUnicodeString CNtQuery::fn_RtlFreeUnicodeString;
- FN_RtlFreeAnsiString CNtQuery::fn_RtlFreeAnsiString;
- bool CNtQuery::m_bInit = false;
- bool CNtQuery::GetAddr()
- {
- m_hNtdll = GetModuleHandle(_T("ntdll.dll"));
- if (m_hNtdll == NULL)
- return false;
- fn_NtQueryDirectoryFile = (FN_NtQueryDirectoryFile)GetProcAddress(m_hNtdll,"NtQueryDirectoryFile");
- fn_NtOpenFile = (FN_NtOpenFile)GetProcAddress(m_hNtdll,"NtOpenFile");
- fn_NtClose = (FN_NtClose)GetProcAddress(m_hNtdll,"NtClose");
- fn_RtlInitUnicodeString = (FN_RtlInitUnicodeString)GetProcAddress(m_hNtdll,"RtlInitUnicodeString");
- fn_RtlInitAnsiString = (FN_RtlInitAnsiString)GetProcAddress(m_hNtdll,"RtlInitAnsiString");
- fn_RtlAnsiStringToUnicodeString = (FN_RtlAnsiStringToUnicodeString)GetProcAddress(m_hNtdll,"RtlAnsiStringToUnicodeString");
- fn_RtlUnicodeStringToAnsiString = (FN_RtlUnicodeStringToAnsiString)GetProcAddress(m_hNtdll,"RtlUnicodeStringToAnsiString");
- fn_RtlFreeUnicodeString = (FN_RtlFreeUnicodeString)GetProcAddress(m_hNtdll,"RtlFreeUnicodeString");
- fn_RtlFreeAnsiString = (FN_RtlFreeAnsiString)GetProcAddress(m_hNtdll,"RtlFreeAnsiString");
- if (!(fn_NtQueryDirectoryFile && fn_NtOpenFile && fn_NtClose && fn_RtlInitUnicodeString))
- {
- return false;
- }
- return true;
- }
- CNtQuery::CNtQuery(void)
- {
- if (!m_bInit)
- m_bInit = GetAddr();
- }
- CNtQuery::~CNtQuery(void)
- {
- }
- HANDLE CNtQuery::FindFirstFile(LPCTSTR strDirectory,PBYTE bytBuffer,ULONG size)
- {
- if (!m_bInit)
- return INVALID_HANDLE_VALUE;
- TCHAR strFolder[MAX_PATH];
- OBJECT_ATTRIBUTES obAttr;
- IO_STATUS_BLOCK objIoStatus;
- NTSTATUS ntStatus;
- HANDLE hFind = NULL;
- UNICODE_STRING strUnicode;
-
- wsprintf(strFolder,_T("\\??\\%s"),strDirectory);
- //'初始化Unicode字符串
- #ifdef UNICODE
- fn_RtlInitUnicodeString(&strUnicode, strFolder);
- #else
- ANSI2UNICODE(strFolder,&strUnicode);
- #endif
- memset(&objIoStatus,0,sizeof(IO_STATUS_BLOCK));
- memset(&obAttr,0,sizeof(OBJECT_ATTRIBUTES));
- obAttr.Length = sizeof(OBJECT_ATTRIBUTES); //'初始化OBJECT_ATTRIBUTES结构
- obAttr.Attributes = OBJ_CASE_INSENSITIVE;
- obAttr.ObjectName = &strUnicode; //'需要打开的文件夹路径
- obAttr.RootDirectory = NULL;
- obAttr.SecurityDescriptor = NULL;
- obAttr.SecurityQualityOfService = NULL;
- //'获取文件夹句柄
- ntStatus = fn_NtOpenFile(&hFind,
- FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,
- &obAttr,
- &objIoStatus,
- 3,
- FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT);
- #ifndef UNICODE
- //释放内存
- fn_RtlFreeUnicodeString(&strUnicode);
- #endif
- if (ntStatus == 0 && hFind != INVALID_HANDLE_VALUE)
- {
-
- //'获取文件夹文件/目录信息,其实这个函数是Kernel32里的FindFirstFile的封装
- ntStatus = fn_NtQueryDirectoryFile(hFind,
- NULL,
- NULL,
- NULL,
- &objIoStatus,
- bytBuffer,
- size,
- FileBothDirectoryInformation,
- TRUE,
- NULL,
- NULL);
- if (ntStatus == 0) //'Nt系列函数一般返回大于零表示成功,而NtQueryDirectoryFile返回零表示成功
- {
- //_tprintf(_T("Succeed!\n"));
- return hFind;
- }else{
- fn_NtClose(hFind);
- }
- }
- return INVALID_HANDLE_VALUE;
- }
- bool CNtQuery::FindNextFile(HANDLE hFind,PBYTE bytBuffer,ULONG size)
- {
- if (!m_bInit)
- return false;
- NTSTATUS ntStatus;
- IO_STATUS_BLOCK objIoStatus;
- //'这是Kernel32 FindNextFile的封装,只是是一次把所有文件/目录都取出来了
- ntStatus = fn_NtQueryDirectoryFile(hFind,
- NULL,
- NULL,
- NULL,
- &objIoStatus,
- bytBuffer,
- size,
- FileBothDirectoryInformation,
- FALSE,
- NULL,
- NULL);
- //_tprintf(_T("ntStatus\n"));
- return (ntStatus == 0);
- }
- void CNtQuery::Enum(LPCTSTR lpszPath)
- {
- if (!m_bInit)
- return;
- #ifndef UNICODE
- ANSI_STRING asfn,asan;
- #endif
- PFILE_BOTH_DIRECTORY_INFORMATION pDir;
- HANDLE hFind;
- LPBYTE bytBuffer;
- wchar_t fileName[_MAX_FNAME];
- wchar_t AlternateName[13];
- TCHAR strPath[MAX_PATH];
- TCHAR strFileName[MAX_PATH];
- ULONG dwDirOffset;
- ULONG iCount = 0;
- ULONG usize = sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + MAX_PATH * 2 - 3;
- bytBuffer = new BYTE[usize];
- //memset(bytBuffer,0,usize);
- lstrcpy(strPath,lpszPath);
- hFind = FindFirstFile(strPath,bytBuffer,usize); //'获取第一个文件/目录对象
- if (hFind == INVALID_HANDLE_VALUE)
- return ;
- pDir = (PFILE_BOTH_DIRECTORY_INFORMATION)bytBuffer;
- //获取FILE_BOTH_DIRECTORY_INFORMATION结构,目的是获取FileNameLength和NextEntryOffset数据
- memcpy(fileName, pDir->FileName, pDir->FileNameLength);
- memcpy(AlternateName,pDir->AlternateName,pDir->AlternateNameLength); //8.3短文件名
- fileName[pDir->FileNameLength / sizeof(wchar_t)] = 0;
- AlternateName[pDir->AlternateNameLength / sizeof(wchar_t)] = 0; //这里的长度都是字节数
- #ifndef UNICODE
- UNICODE2ANSI(fileName, &asfn);
- UNICODE2ANSI(AlternateName, &asan);
- wsprintf(strFileName,_T("%s%s"),strPath, asfn.Buffer);
- _tprintf(_T("%02d %8s\t%s\n"),pDir->AlternateNameLength, asan.Buffer, strFileName);
- fn_RtlFreeAnsiString(&asfn);
- fn_RtlFreeAnsiString(&asan);
- #else
- wsprintf(strFileName,_T("%s%s"),strPath,fileName);
- _tprintf(_T("%02d %8s\t%s\n"),pDir->AlternateNameLength, AlternateName, strFileName);
- #endif
-
- delete[] bytBuffer;
-
- usize = (sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + (260 * 2 - 3)) * 0x2000;
- bytBuffer = new BYTE[usize];
- iCount = 1;
- while (FindNextFile(hFind,bytBuffer,usize)) //虽然分配了许多空间了,但是仍可能不能把全部文件列举出来,因此,这里需要进一步测试
- {
- dwDirOffset = 0;
- //遍历缓存
- while(true)
- {
- //移动指针
- pDir = (PFILE_BOTH_DIRECTORY_INFORMATION)(bytBuffer + dwDirOffset);
- //得到FILE_BOTH_DIRECTORY_INFORMATION结构
-
- memcpy(fileName, pDir->FileName, pDir->FileNameLength); //文件名
- memcpy(AlternateName,pDir->AlternateName,pDir->AlternateNameLength); //8.3短文件名
- AlternateName[pDir->AlternateNameLength / sizeof(wchar_t)] = 0; //这里的长度都是字节数
- fileName[pDir->FileNameLength / sizeof(wchar_t)] = 0;
- #ifndef UNICODE
- UNICODE2ANSI(fileName, &asfn);
- UNICODE2ANSI(AlternateName, &asan);
- wsprintf(strFileName,_T("%s%s"),strPath, asfn.Buffer);
- _tprintf(_T("%02d %8s\t%s\n"),pDir->AlternateNameLength, asan.Buffer, strFileName);
- fn_RtlFreeAnsiString(&asfn);
- fn_RtlFreeAnsiString(&asan);
- #else
- wsprintf(strFileName,_T("%s%s"),strPath,fileName);
- _tprintf(_T("%02d %8s\t%s\n"),pDir->AlternateNameLength, AlternateName, strFileName);
- #endif
- //这里如果是目录可以递归遍历目录下所有文件/目录,可以自己封装一个递归函数吧
- iCount++;
- if (pDir->NextEntryOffset == 0)
- break;
- dwDirOffset += pDir->NextEntryOffset; //这里指向下一个FILE_BOTH_DIRECTORY_INFORMATION结构在内存中的位置
- }
- }
- delete[] bytBuffer;
- fn_NtClose(hFind);
- _tprintf(_T("\nfilecount: %d\n"),iCount);
- }
- //RtlAnsiStringToUnicodeString()
- //RtlUnicodeStringToAnsiString()
- //当第3个参数为TRUE时,系统将新分配内存,所以要记得调用RtlFreeUnicodeString()和RtlFreeAnsiString()释放掉。
- NTSTATUS CNtQuery::ANSI2UNICODE(LPCSTR lpBuf, PUNICODE_STRING pUnicodeString, BOOLEAN AllocateDestinationString)
- {
- ANSI_STRING as;
- fn_RtlInitAnsiString( &as, lpBuf );
- return fn_RtlAnsiStringToUnicodeString( pUnicodeString, &as, AllocateDestinationString );
- }
- NTSTATUS CNtQuery::UNICODE2ANSI(LPCWSTR lpBuf, PANSI_STRING pAnsiString, BOOLEAN AllocateDestinationString)
- {
- UNICODE_STRING ns;
- fn_RtlInitUnicodeString( &ns, lpBuf );
- return fn_RtlUnicodeStringToAnsiString( pAnsiString, &ns, AllocateDestinationString );
- }
复制代码 |
|