📄 buffermgr.cpp
字号:
/*
* Openmysee
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
// BufferMgr.cpp: implementation of the BufferMgr class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BufferMgr.h"
#include <tlhelp32.h>
namespace NPLayer1 {
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BufferMgr::BufferMgr() : blockArray(NULL), blockNum(0), hBufferFile(NULL) {
}
BufferMgr::~BufferMgr() {
if(hBufferFile) {
// 删除文件
CloseHandle(hBufferFile);
hBufferFile = NULL;
}
::DeleteFile(bufferFileName.data());
delete [] blockArray;
blockArray = NULL;
blockNum = 0;
}
P2P_RETURN_TYPE BufferMgr::Init(string fullPath, bool& bufFileModified, UINT randNum, UINT bufferSize) {
bufFileModified = false;
// 只能初始化一次,如果已经初始化了,就返回错误
if(blockArray)
return PRT_DUP_INIT;
// 如果没有给出缓冲文件的全路径,则在缓冲文件夹建立一个缓冲文件
GENERATE_FILENAME:if(fullPath.empty()) {
// Filter文件所在的路径
char buf[MAX_PATH_EX];
if(!GetSelfModulePath(buf, MAX_PATH_EX))
return PRT_SYS;
bufferFileName = buf;
bufferFileName.append("GB");
itoa(randNum, buf, 10);
bufferFileName.append(buf);
bufferFileName.append(".tmp");
}
else
bufferFileName = fullPath;
// 缓冲文件的最大长度
bufferFileSize = bufferSize;
// 查找缓冲文件, 如果没有找到,则创建一个
WIN32_FIND_DATA fileData;
HANDLE hFind = FindFirstFile(bufferFileName.data(), &fileData);
if(hFind == INVALID_HANDLE_VALUE) {
for(;;) {
// 创建缓冲文件
if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
int err = GetLastError();
if(err == 3) {
// 创建文件失败,因为有不存在的中间目录,需要首先创建中间目录
int index = 0;
string temp;
do {
int offset = bufferFileName.find_first_of('\\', index);
if(offset == -1)
break;
temp = bufferFileName.substr(0, offset);
index = offset+1;
if(!CreateDirectory(temp.data(), NULL)) {
int ret = GetLastError();
if(ret == ERROR_ALREADY_EXISTS || ret == ERROR_ACCESS_DENIED)
continue;
break;
}
}while(1);
// Create Again
continue;
}
else
return PRT_SYS;
}
// 成功创建文件
bufFileModified = true;
break;
}
// 将缓冲文件长度设为0
ExSetFileSize(hBufferFile, 0);
}
else if(fullPath.empty()) {
// 如果是随机生成的文件名,结果发现重名,则把randnum+1,再次尝试
randNum++;
goto GENERATE_FILENAME;
}
else {
FindClose(hFind);
// 打开缓冲文件
if(!ExCreateFile(hBufferFile, bufferFileName.data(), OPEN_EXISTING)) {
//assert(0);
if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
//assert(0);
return PRT_CANNOT_OPEN_BUF;
}
bufFileModified = true;
}
}
// 如果存在的文件大小超过目标文件大小,则将其大小设置为目标文件大小
UINT realBufSize = ::GetFileSize(hBufferFile, NULL);
if(realBufSize == INVALID_FILE_SIZE)
return PRT_SYS;
if(realBufSize > bufferFileSize) {
// 将缓冲文件长度设为目标文件大小
ExSetFileSize(hBufferFile, bufferFileSize);
realBufSize = bufferFileSize;
bufFileModified = true;
}
// 检查磁盘空间是否足够
ULARGE_INTEGER availableBytes, totalBytes;
string purepath = bufferFileName;
int index = purepath.find_last_of('\\');
if(index != -1)
purepath.resize(index);
else
return PRT_SYS;
if(!GetDiskFreeSpaceEx(purepath.data(), &availableBytes, &totalBytes, NULL)) {
return PRT_SYS;
}
else {
if(availableBytes.QuadPart < bufferFileSize-realBufSize) {
// not enough space on disk
return PRT_DISK_FULL;
}
}
// 计算数组大小, 如果不能整除,则加一
blockNum = bufferFileSize/BLOCK_SIZE;
if(bufferFileSize%BLOCK_SIZE != 0)
blockNum++;
// 初始化数组
blockArray = new bool[blockNum];
if(!blockArray)
return PRT_ALLOC;
// 将所有成员置为false, 即标记所有快为未使用
fill(blockArray, blockArray+blockNum, false);
return PRT_OK;
}
UINT BufferMgr::GetEmptyIndex(UINT randNum) {
// 如果尚未初始化,则返回错误
if(!blockArray)
return UINT_MAX;
// 使用随机数选择缓冲区中的空位,这是为了防止有人Hook我们的缓冲区
// 如果我们是顺序存储的,那么很容易就从新建缓冲区中按顺序读出数据
// 所以要使用随即的存储位置
// 1. 根据随机数,确定随机位置
UINT randPos = randNum%blockNum;
// 2. 将遍历用的iterator移动到该随机位置
UINT i = randPos;
// 3. 设定第一轮循环的开始结束位置,从随机位置到hash_map尾
UINT start = i;
UINT end = blockNum;
for(; ;++i) {
if(i == end) {
if(end == blockNum) {
// 4. 第一轮循环结束,开始第二轮,从头到随机位置
i = 0;
end = start;
// 如果两者相等说明只有一个元素,而且第一轮已经比较过了,所以跳出循环
if(i == end) {
break;
}
}
else {
// 5. 第二轮循环结束,跳出循环
break;
}
}
// 如果发现一个未使用的块,则标记为已使用,并返回数组下标
if(!blockArray[i]) {
blockArray[i] = true;
return i;
}
}
return UINT_MAX;
}
void BufferMgr::EraseIndex(UINT index) {
// 如果尚未初始化,则返回
if(!blockArray)
return;
// 下标越界
if(index >= blockNum)
return;
// 将此块标记为未使用
blockArray[index] = false;
}
// 获取剩余空间大小
UINT BufferMgr::GetEmptySpace() {
return BLOCK_SIZE*count(blockArray, blockArray+blockNum, false);
}
P2P_RETURN_TYPE BufferMgr::GetIndexData(UINT index, UINT offset, LPVOID data, UINT size) {
// 如果参数错误或者尚未初始化,则返回错误
if(!data || !blockArray)
return PRT_WRONG_ARG;
// 如果超过边界,则返回错误
if(index >= blockNum)
return PRT_WRONG_ARG;
// 如果要求的数据过大,则返回错误
if(offset+size > BLOCK_SIZE)
return PRT_WRONG_ARG;
// 如果要求的是最后一块,但是数据长度过大,则返回错误
if(index == blockNum-1 && offset+size > bufferFileSize-index*BLOCK_SIZE)
return PRT_WRONG_ARG;
// 如果此块不存在,则返回出错
//if(!blockArray[index])
// return PRT_WRONG_ARG;
// 移动文件指针到偏移位置
if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE+offset))
return PRT_SYS;
// 如果读到的数据长度不等于需要的数据长度,则返回错误
if(ExReadFile(hBufferFile, data, size) != size)
return PRT_SYS;
return PRT_OK;
}
P2P_RETURN_TYPE BufferMgr::PutIndexData(UINT index, LPVOID data, UINT size) {
// 如果参数错误或者尚未初始化,则返回错误
if(!data || !blockArray)
return PRT_WRONG_ARG;
// 如果超过边界,则返回错误
if(index >= blockNum)
return PRT_WRONG_ARG;
// 如果数据过大,则返回错误
if(size > BLOCK_SIZE)
return PRT_WRONG_ARG;
// 如果是最后一块,但是数据长度过大,则返回错误
if(index == blockNum-1 && size > bufferFileSize-index*BLOCK_SIZE)
return PRT_WRONG_ARG;
/*
// 在GetEmptyIndex里已经把这里划分出去了!
// 如果此块已经存在,则返回出错
if(blockArray[index])
return FALSE;
*/
// 移动文件指针到偏移位置
if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE))
return PRT_SYS;
// 如果写入的数据长度不等于实际的数据长度,则返回错误
if(ExWriteFile(hBufferFile, data, size) != size)
return PRT_SYS;
return PRT_OK;
}
BOOL BufferMgr::ExSetFileSize(HANDLE handle, UINT size) {
BOOL ret = TRUE;
if(!ExSetFilePointer(handle, size))
ret = FALSE;
else if(0 == SetEndOfFile(handle)) {
ret = FALSE;
}
return ret;
}
UINT BufferMgr::ExReadFile(HANDLE handle, LPVOID buf, UINT toBeRead) {
UINT readCount = 0;
DWORD tmpRead;
while(readCount < toBeRead) {
BOOL success = ReadFile(
handle, // file handler
(char*)buf+readCount, // current buffer position
toBeRead - readCount, // remaining bytes to be read
&tmpRead, // read bytes
NULL); // not overlaped
if(!success)
return 0;
if(tmpRead == 0) // no more data
return 0;
readCount += tmpRead;
}
return readCount;
}
UINT BufferMgr::ExWriteFile(HANDLE handle, LPCVOID buf, UINT toBeWrite) {
UINT writeCount = 0;
DWORD tmpWrite;
while(writeCount < toBeWrite) {
BOOL success = WriteFile(
handle, // file handler
(char*)buf+writeCount, // current buffer position
toBeWrite-writeCount, // remaining bytes to be read
&tmpWrite, // written bytes
NULL); // not overlaped
if(!success) {
return FALSE;
}
writeCount += tmpWrite;
}
return writeCount;
}
BOOL BufferMgr::ExSetFilePointer(HANDLE handle, UINT offset) {
if(-1 == SetFilePointer(handle,
offset,
NULL,
FILE_BEGIN)) {
return FALSE;
}
return TRUE;
}
BOOL BufferMgr::ExCreateFile(HANDLE& handle,
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) {
handle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
if(handle == INVALID_HANDLE_VALUE) {
return FALSE;
}
return TRUE;
}
BOOL BufferMgr::ExCreateFile(HANDLE& handle, LPCTSTR lpFileName, DWORD dwCreationDisposition) {
handle = CreateFile(lpFileName,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(handle == INVALID_HANDLE_VALUE) {
return FALSE;
}
return TRUE;
}
BOOL BufferMgr::GetSelfModulePath(LPTSTR buf, DWORD nSize) {
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
if(hModuleSnap == INVALID_HANDLE_VALUE)
return FALSE;
// Set the size of the structure before using it.
me32.dwSize = sizeof(MODULEENTRY32);
// Retrieve information about the first module,
// and exit if unsuccessful
if(!Module32First(hModuleSnap, &me32)) {
CloseHandle(hModuleSnap); // Must clean up the snapshot object!
return FALSE;
}
// Now walk the module list of the process,
// and display information about each module
do
{
_tcsupr(me32.szModule);
if( _tcsncmp(me32.szModule, _T("LAYER1.DLL"), _tcslen(_T("LAYER1.DLL"))) != NULL ||
_tcsncmp(me32.szModule, _T("LAYER1D.DLL"), _tcslen(_T("LAYER1D.DLL"))) != NULL) {
if(_tcslen(me32.szExePath) >= nSize)
return FALSE;
_tcscpy(buf, me32.szExePath);
char* index = _tcsrchr(buf, _T('\\'));
if(index == 0)
return FALSE;
index[1] = 0;
return TRUE; // Find target module name
}
} while(Module32Next(hModuleSnap, &me32));
// Do not forget to clean up the snapshot object.
CloseHandle(hModuleSnap);
return FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -