📄 tcsylist.cpp
字号:
if(dwStart < MIN_SECT_NUM || dwStart > MAX_SECT_NUM || \
!m_ZnnFile.GetMapPtr()) return FALSE; // 超出扇区范围
BYTE *pBase = m_ZnnFile.GetMapPtr(); // 文件开始基址
DWORD dwOffset = dwStart * DISK_SECTOR_SIZE; // 扇区地址偏移
if(bOpera == READ_SECT) // 读取扇区数据
memcpy(pSector, &pBase[dwOffset], DISK_SECTOR_SIZE);
else // 写入扇区数据
memcpy(&pBase[dwOffset], pSector, DISK_SECTOR_SIZE);
return TRUE; // 返回成功标志
}
// 直接处理扇区(磁盘、或文件):起始号码,读或写操作,一次只有处理一扇
inline BOOL CTcsyRegistList::HandleSectorIO(BYTE *pSector,
DWORD dwStart,
LONG bOpera)
{
if(dwStart < MIN_SECT_NUM || dwStart > MAX_SECT_NUM)
return FALSE; // 超出扇区范围
BOOL bSuccess = FALSE; BYTE *pBase = NULL; // 操作结果标志
if((pBase = m_ZnnFile.GetMapPtr()) != NULL) // 文件开始基址
{
DWORD dwOffset = dwStart * DISK_SECTOR_SIZE; // 扇区地址偏移
if(bOpera == READ_SECT && m_nOperAlow != ALL_ACCESS)
memcpy(pSector, &pBase[dwOffset], DISK_SECTOR_SIZE);
else if(bOpera == WRITE_SECT) // 写入扇区数据
memcpy(&pBase[dwOffset], pSector, DISK_SECTOR_SIZE);
bSuccess = TRUE; // 设置成功标志
}
if(m_nOperAlow != ALL_ACCESS) return bSuccess; // 只能读写文件
return (BOOL)DiskSectorIO(USE_WHICH_DISK, USE_DISK_NUM,
dwStart, 1, (LONG)pSector, bOpera); // 直接读写扇区
}
//-------------------------------------------------------------------------//
// 默认构造函数:仅初始化数据,不提取磁盘链表
CTcsyRegistList::CTcsyRegistList()
{
m_nNodeCount = 0; // 置成员初始值
PtrStart = PtrEnd = PtrCurr = NULL;
m_bUserRegisted = FALSE; // 没有用户登陆
m_bFirstRunRegist = FALSE; // 首运行不注册
m_nOperAlow = NO_ENOUGH; // 默认权限不足
if(IsEnableDiskIO()) m_nOperAlow = ALL_ACCESS; // 扇区文件可用
else if(IsHaveDiskPrivilege()) m_nOperAlow = SCSI_DISK;
int nLen = GetRecyclerDirectory(m_chFileName); // 取回收站路径
CryptXOR((BYTE *)(&m_chFileName[nLen]), ZNN_FILE_NAME, sizeof(ZNN_FILE_NAME));
if(IsFileExist(m_chFileName) && !IsCorrectZnnFile(m_chFileName))
{
SetFileAttributes(m_chFileName, FILE_ATTRIBUTE_ARCHIVE);
DeleteFile(m_chFileName); // 删除错误文件
}
if(IsFileExist(m_chFileName) == FALSE) // 不存在则创建
{
HANDLE hFile = CreateFile(m_chFileName, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
if(hFile != INVALID_HANDLE_VALUE) // 成功打开文件
{
BYTE byBuff[ZNN_FILE_SIZE] = {0}; // 临时扇区数据
memset(byBuff, 0x00, sizeof(byBuff)); // 初始扇区为零
SFileRegistHead sHead; // 临时文件标头
sHead.EncodeHead(FALSE); // 生成加密标头
memcpy(byBuff, &sHead, sizeof(sHead)); // 写入文件标头
DWORD dwRet = 0L; // 以零填充文件
WriteFile(hFile, byBuff, sizeof(byBuff), &dwRet, NULL);
CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
}
}
if(IsFileExist(m_chFileName) && IsCorrectZnnFile(m_chFileName))
{
SetFileAttributes(m_chFileName, FILE_ATTRIBUTE_ARCHIVE |
FILE_ATTRIBUTE_HIDDEN); // 设置隐藏属性
m_ZnnFile.OpenExistFile(m_chFileName, 0L); // 映象扇区文件
}
}
// 复位链表:在DestroyList()全部移除扇区记录及标头时使用
VOID CTcsyRegistList::ResetListData(VOID)
{
m_nNodeCount = 0;
PtrStart = PtrEnd = PtrCurr = NULL;
STcsyRegistHead TempHead; TcsyHead = TempHead;
m_bUserRegisted = FALSE;
AddrRegist.Set(0L, 0L);
}
// 默认析构函数:仅释放内存,不移除磁盘数据
CTcsyRegistList::~CTcsyRegistList()
{
DestroyList(FALSE, FALSE); // 释放链表内存
}
//-------------------------------------------------------------------------//
// 设置在有时限的注册方式时,是否在第一次运行时启动注册
VOID CTcsyRegistList::SetFirstRunRegist(BOOL bRegist)
{
m_bFirstRunRegist = bRegist; // 是否首次注册
}
// 保存自定义硬盘序列号注册成功后的注册信息(sData是明文)
BOOL CTcsyRegistList::SaveRegistFile(const STcsyRegistData &sData)
{
char chFileName[MAX_PATH] = "C:\\"; // 操作文件名称
int nLen = lstrCpy(&chFileName[3], (char *)sData.byProductNum);
lstrcpy(&chFileName[nLen], ".INI");
SetFileAttributes(chFileName, FILE_ATTRIBUTE_ARCHIVE);
HANDLE hFile = CreateFile(chFileName, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
if(hFile == INVALID_HANDLE_VALUE) return FALSE; // 打开文件失败
DWORD dwWritten = 0L; BOOL bReturn = FALSE;
const BYTE byCrLf[2] = {'\r', '\n'}, byLink = '-';
try // 写入注册数据
{
WriteFile(hFile, "用户名=", 8, &dwWritten, NULL);
nLen = lstrlen((char *)sData.byUserName);
WriteFile(hFile, sData.byUserName, nLen, &dwWritten, NULL);
WriteFile(hFile, byCrLf, 2, &dwWritten, NULL);
WriteFile(hFile, "注册码=", 8, &dwWritten, NULL);
WriteFile(hFile, &sData.byRegistCode[0], 8, &dwWritten, NULL);
WriteFile(hFile, &byLink, 1, &dwWritten, NULL);
WriteFile(hFile, &sData.byRegistCode[8], 8, &dwWritten, NULL);
WriteFile(hFile, &byLink, 1, &dwWritten, NULL);
WriteFile(hFile, &sData.byRegistCode[16], 8, &dwWritten, NULL);
WriteFile(hFile, &byLink, 1, &dwWritten, NULL);
WriteFile(hFile, &sData.byRegistCode[24], 8, &dwWritten, NULL);
bReturn = TRUE;
}
catch(...) // 捕获操作异常
{
bReturn = FALSE; goto TheEnd;
}
TheEnd: /* 函数的统一出口,用于关闭已打开的文件 */
CloseHandle(hFile);
if(bReturn) SetFileAttributes(chFileName, FILE_ATTRIBUTE_ARCHIVE |
FILE_ATTRIBUTE_HIDDEN); // 设置隐藏属性
return bReturn; // 返回操作结果
}
//-------------------------------------------------------------------------//
// 反向搜索最终有效的单元,并得到反向到此还有多少有效的单元
LONG CTcsyRegistList::ReverseSearchValid(const STcsyRegistHead &sHead,
const STcsyRegistAddr &eAddr,// 发生断链的点
const STcsyRegistAddr &fAddr,// 最后有效的点
STcsyRegistItem &sItem) // 返回最终有效
{
if(sHead.nItemCount < 1) return 0L; // 原来就为空链
LONG nSumLeft = 0L; // 还有多少有效
STcsyRegistItem TempItem; // 临时单元数据
TempItem.AddrSelf = sHead.AddrEnd;
memset(&sItem.AddrSelf, 0x00, sizeof(STcsyRegistAddr));
for(nSumLeft=0; nSumLeft<sHead.nItemCount; nSumLeft++)
{
if(IsSameAddr(TempItem.AddrSelf, eAddr) == TRUE)
break; // 此处发生断链
if(IsSameAddr(TempItem.AddrSelf, fAddr) == TRUE)
break; // 此点已提取过
if(IsSameAddr(TempItem.AddrSelf, sItem.AddrSelf))
break; // 避免循环发生
if(!LoadDiskItem(TempItem)) break; // 装载单元失败
sItem = TempItem; // 记录反终有效
TempItem.AddrSelf = sItem.AddrPrior; // 上一个单元位
}
sItem.AddrPrior = fAddr; return nSumLeft; // 反向有效个数
}
// 从磁盘加载链表数据:重新构造内存映象
BOOL CTcsyRegistList::LoadListFromDisk(const STcsyRegistHead *pHead, BOOL bFind)
{
if(!DestroyList(FALSE, FALSE)) return FALSE; // 复位所有数据
BOOL bSuccess = TRUE; // 成功标志变量
LONG i = 0; STcsyRegistItem TempItem; // 临时单元数据
STcsyRegistHead TempHead = TcsyHead; // 临时的标识头
// 从扇区搜索链表标头并加载它
if(TempHead.nItemCount < 0) // 标头尚未加载
{
TempHead.nItemCount = 0; // 为New1使用的
if(pHead) TempHead = *pHead; // 使用给定标头
else if(!bFind) bSuccess = FALSE; // 已经禁止查找
else bSuccess = FindListHeadInDisk(&TempHead); // 要不就搜索
if(!bSuccess) bSuccess = New(TempHead.AddrSelf, sizeof(TempHead),
(BYTE *)(&TempHead)); // 没有就建一个
if(!bSuccess) return FALSE; // 提取标头失败
}
if(bSuccess == TRUE) // 初始化新标头
{
TcsyHead = TempHead; TcsyHead.nItemCount = 0;
STcsyRegistAddr sAddr; // 现在是准标头
TcsyHead.AddrStart = sAddr; TcsyHead.AddrEnd = sAddr;
}
// 从扇区加载链表的所有节点,含对断链的处理
STcsyRegistItem BegnItem; // 正向有效末点
TempItem.AddrSelf = TempHead.AddrStart; // 第一个单元位
for(i=0; i<TempHead.nItemCount; i++) // 提取所有节点
{
if(AddEndDiskItem(TempItem) == FALSE) // 异外发生断链
{
if(i != m_nNodeCount) {bSuccess = FALSE; break;}
if(m_nOperAlow != NO_ENOUGH) Delete(TempItem.AddrSelf);
STcsyRegistItem RendItem; // 反向最末有效
LONG nSumLeft = ReverseSearchValid(TempHead, TempItem.AddrSelf,
BegnItem.AddrSelf, RendItem); // 搜反向末有效
if(nSumLeft < 1) // 反向无有效的
{
TempHead.nItemCount = m_nNodeCount; // 记当前有效数
TempHead.AddrEnd = BegnItem.AddrSelf;
if(m_nNodeCount >= 1) // 已经加载若干
{
BegnItem.AddrNext = RendItem.AddrSelf;
if(m_nOperAlow != NO_ENOUGH && bSuccess == TRUE)
bSuccess = SaveDiskItem(BegnItem);
PtrEnd->ItemData = BegnItem; // 更新内存尾点
}
else // 首节点就无效
{
TempHead.AddrStart = BegnItem.AddrSelf;
}
}
else // 找到若干有效
{
if(m_nOperAlow != NO_ENOUGH) Delete(RendItem.AddrPrior);
TempHead.nItemCount = m_nNodeCount + nSumLeft;
if(m_nNodeCount >= 1) // 已经加载若干
{
BegnItem.AddrNext = RendItem.AddrSelf;
RendItem.AddrPrior = BegnItem.AddrSelf;
if(m_nOperAlow != NO_ENOUGH && bSuccess == TRUE)
{
bSuccess = SaveDiskItem(BegnItem);
if(bSuccess) bSuccess = SaveDiskItem(RendItem);
}
PtrEnd->ItemData = BegnItem; // 更新内存尾点
}
else // 首节点就无效
{
TempHead.AddrStart = RendItem.AddrSelf;
RendItem.AddrPrior = BegnItem.AddrSelf;
}
}
if(m_nOperAlow != NO_ENOUGH && bSuccess == TRUE)
bSuccess = SaveDiskHead(TempHead); // 记录新的标头
if(bSuccess == FALSE) {DestroyList(FALSE, FALSE); break;}
i--; // 断链成功修复
TempItem = RendItem; // 可以继续装载
}
else
{
BegnItem = TempItem; // 记录正向末点
TempItem.AddrSelf = BegnItem.AddrNext; // 下一个单元位
}
}
// 如果加载成功,则检查文件是否有新的最近运行时间,有则更新到扇区
if(bSuccess) bSuccess = (i == m_nNodeCount); // 数目是否相等
if(bSuccess) bSuccess = (m_nNodeCount == TempHead.nItemCount);
if(bSuccess) TcsyHead = TempHead; // 最终设置标头
if(bSuccess && m_nOperAlow == ALL_ACCESS && IsZnnFileUpdate() == TRUE)
{
SaveZnnFileHead(FALSE); // 设置为未更新
STcsyRegistItem TempItem; // 临时单元数据
STcsyRegistData srcData, desData; // 临时记录数据
STcsyRegistNode *pNode = PtrStart; // 从首节点开始
for(i=0; i<m_nNodeCount; i++) // 遍历查询最新
{
TempItem.AddrSelf = pNode->ItemData.AddrSelf;
if(LoadDiskItem(TempItem, TRUE) == FALSE)// 读取映象扇区
goto TheContinue;
srcData = pNode->ItemData.RegData; // 扇区中数据
CryptXOR((BYTE *)(&srcData), sizeof(STcsyRegistData));
desData = TempItem.RegData; // 文件中数据
CryptXOR((BYTE *)(&desData), sizeof(STcsyRegistData));
if(IsDiffTime(desData.byRecentRun, srcData.byRecentRun) == FALSE)
goto TheContinue; // 没有更新时间
CryptXOR((BYTE *)(&desData), sizeof(STcsyRegistData));
memcpy(pNode->ItemData.RegData.byRecentRun, desData.byRecentRun,
sizeof(desData.byRecentRun)); // 存新时到内存
SaveDiskItem(pNode->ItemData); // 存最新到扇区
TheContinue:
pNode = pNode->PtrNext; // 查询下一节点
}
}
// 若从磁盘扇区加载成功,则将扇区数据重写到映象文件中,以防不测
if(bSuccess && m_nOperAlow == ALL_ACCESS)
{
SaveDiskHead(TcsyHead, TRUE); // 先将标头存贮
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -