📄 tcsylist.cpp
字号:
STcsyRegistNode *pNode = PtrStart; // 从首节点开始
for(i=0; i<m_nNodeCount; i++) // 遍历查询单元
{
SaveDiskItem(pNode->ItemData, TRUE); // 存贮到映象扇
pNode = pNode->PtrNext; // 取下一点指针
}
}
return bSuccess; // 返回处理结果
}
// 从释放链表内存:移除磁盘单元数据(可选)、移除磁盘头数据(可选)
BOOL CTcsyRegistList::DestroyList(BOOL bDelItem, BOOL bDelHead)
{
BOOL bSuccess = TRUE; LONG nReturn = DEL_SUCCESS;
if(bDelItem == FALSE && m_nNodeCount > 0) // 最近运行
{
STcsyRegistNode *pNode = PtrStart;
BYTE byCurrDate[sizeof(pNode->ItemData.RegData.byRecentRun)];
GetCurrDate(byCurrDate);
CryptXOR(byCurrDate, sizeof(byCurrDate));
for(long i=0; i<m_nNodeCount; i++)
{
memcpy(pNode->ItemData.RegData.byRecentRun, byCurrDate,
sizeof(byCurrDate));
SaveDiskItem(pNode->ItemData);
pNode = pNode->PtrNext; if(!pNode) break;
}
if(m_nOperAlow != ALL_ACCESS) SaveZnnFileHead(TRUE);
}
while(bSuccess && m_nNodeCount > 0) // 全部释放
{
nReturn = DelEnd(bDelItem);
if(nReturn == DEL_FAILURE) bSuccess = FALSE; // 删除失败
if(nReturn != DEL_SUCCESS) break;
}
if(bSuccess && bDelItem && bDelHead && TcsyHead.nItemCount >= 0)
{
bSuccess = Delete(TcsyHead.AddrSelf); // 移除标头
if(bSuccess) ResetListData();
}
return bSuccess; // 返回结果
}
//-------------------------------------------------------------------------//
// 在扇区中,申请空区,自动保留大小、延拓大小,即刻写入给定数据
BOOL CTcsyRegistList::New(STcsyRegistAddr &sAddr, WORD wDataSize, const BYTE *pData)
{
WORD wTotalSize = wDataSize + 2 * EXTEND_BYTES + NEW_RECSIZE;
if(wDataSize < 1 || wTotalSize > DISK_SECTOR_SIZE) return FALSE;
DWORD i = 0; BYTE *pOccur = NULL, *pStart = NULL;// 在扇区内偏移
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
for(i=MIN_SECT_NUM; i<=MAX_SECT_NUM; i++) // 遍历所有扇区
{
if(HandleSectorIO(byBuff, i, READ_SECT) == FALSE)
break; // 读取磁盘扇区
pOccur = CSearchBin::SearchEmptyArea(byBuff, sizeof(byBuff),
wTotalSize, BYTE_EMPTY);
if(pOccur == NULL) continue; // 搜索连续空域
pStart = pOccur + EXTEND_BYTES + NEW_RECSIZE;// 真正开始点
WORD *pWord = (WORD *)(pStart - sizeof(WORD));
*pWord = wDataSize; // 记录使用大小
*((BYTE *)pWord - 1) = EXTEND_BYTES; // 记录延拓大小
LONG nByteOffs = (LONG)(pStart - byBuff); // 求取偏移字节
if(pData != NULL) // 填充原始数据
{
memcpy(pStart, pData, wDataSize); // 拷贝已有数据
WORD wCrcSize = wDataSize - sizeof(DWORD);// 校验数据大小
DWORD *pDword = (DWORD *)(&pStart[wCrcSize]);
STcsyRegistAddr *pAddr = (STcsyRegistAddr *)((BYTE *)pDword \
- sizeof(STcsyRegistAddr)); // 加入位置偏移
pAddr->dwSectNum = i; pAddr->nByteOffs = nByteOffs;
*pDword = GenerateCRC32(pStart, wCrcSize); // 加入校验码
BYTE byKeys[sizeof(DATA_KEYS)]; // 取回原加密钥
CryptXOR(byKeys, DATA_KEYS, sizeof(DATA_KEYS));
SckDesBin(0, pStart, wDataSize, byKeys); // 64位加密目标
}
else memset(pStart, BYTE_FILLIN, wDataSize); // 填充标记字符
if(HandleSectorIO(byBuff, i, WRITE_SECT) == FALSE)
break; // 写入磁盘扇区
sAddr.dwSectNum = i; // 返回:扇区号
sAddr.nByteOffs = nByteOffs; // 返回:偏移量
return TRUE; // 成功申请空域
}
return FALSE; // 已没有空闲啦
}
// 释放磁盘的本身占有的数据空间,并恢复原始填充值,不清空原地址
BOOL CTcsyRegistList::Delete(STcsyRegistAddr sAddr)
{
if(IsValidAddr(sAddr) == FALSE) return FALSE; // 超越扇区范围
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
if(HandleSectorIO(byBuff, sAddr.dwSectNum, READ_SECT) == FALSE)
return FALSE; // 读取磁盘扇区
BYTE *pStart = &byBuff[sAddr.nByteOffs]; // 单元开始位置
WORD *pWord = (WORD *)(pStart - sizeof(WORD)); // 已使用的大小
BYTE *pCurr = (BYTE *)pWord - sizeof(BYTE); // 延拓空间大小
BYTE byExtend = *pCurr, byEmpty = *(pCurr - 1); // 两端延拓大小
WORD wTotalSize = *pWord + 2 * byExtend + NEW_RECSIZE;
if(*pWord < 1 || byExtend < 1 || byExtend > 10 ||// 检测各项大小
wTotalSize > DISK_SECTOR_SIZE) return FALSE;
if(byEmpty != 0x00 && byEmpty != 0xFF) return FALSE;
WORD nDataLen = byExtend + NEW_RECSIZE; // 前端的延拓值
if(!IsKeepAs(pStart - nDataLen, byExtend, byEmpty)) return FALSE;
if(!IsKeepAs(pStart + *pWord, byExtend, byEmpty)) return FALSE;
memset(pStart - nDataLen, byEmpty, wTotalSize); // 恢复原来的值
BOOL bSuccess = HandleSectorIO(byBuff, sAddr.dwSectNum, WRITE_SECT);
if(bSuccess) {sAddr.dwSectNum = 0; sAddr.nByteOffs = 0;}
return bSuccess; // 返回释放结果
}
//-------------------------------------------------------------------------//
// 在磁盘扇区即定范围内查找注册链表的标头,返回标头数据(可选)
BOOL CTcsyRegistList::FindListHeadInDisk(STcsyRegistHead *pHead)
{
DWORD i = 0; LONG nOffset = 0; // 在扇区内偏移
BYTE byHeadFlag[sizeof(TcsyHead.byHeadFlag)]; // 待搜索的标识
memcpy(byHeadFlag, TcsyHead.byHeadFlag, sizeof(byHeadFlag));
BYTE byKeys[sizeof(DATA_KEYS)]; // 取回原加密钥
CryptXOR(byKeys, DATA_KEYS, sizeof(DATA_KEYS)); // 搜索标头密文
SckDesBin(0, byHeadFlag, sizeof(byHeadFlag), byKeys);
CSearchBin sck(byHeadFlag, sizeof(byHeadFlag), 3);
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
for(i=MIN_SECT_NUM; i<=MAX_SECT_NUM; i++) // 搜索目标扇区
{
if(HandleSectorIO(byBuff, i, READ_SECT) == FALSE)
break; // 读取磁盘扇区
nOffset = sck.FindBin(byBuff, sizeof(byBuff));
if(nOffset < 0) continue; // 搜索到头标签
STcsyRegistHead TempHead; // 临时的标识头
memcpy(&TempHead, &byBuff[nOffset], sizeof(TempHead));
SckDesBin(1, (BYTE *)(&TempHead), sizeof(TempHead), byKeys);
if(TempHead.nItemCount < 0) continue; // 记录总数有误
LONG nOff = OFFSET(TempHead, dwValCRC32); // 取位置偏移量
if(GenerateCRC32((BYTE *)(&TempHead), nOff) != TempHead.dwValCRC32)
{DirectRemove(i, nOffset); continue;} // 校验数据失败
TempHead.AddrSelf.dwSectNum = i; // 修正扇区偏移
TempHead.AddrSelf.nByteOffs = nOffset;
if(pHead) *pHead = TempHead; return TRUE; // 需要则返回值
}
return FALSE; // 没有找到标头
}
// 将临时标头更新到已有扇区,执行拷贝写入,无须返回数据:要再加密
BOOL CTcsyRegistList::SaveDiskHead(STcsyRegistHead sHead, BOOL bFileIO)
{
if(!IsValidAddr(sHead.AddrSelf)) return FALSE; // 超越扇区范围
if(sHead.nItemCount < 0) return FALSE; // 不是有效标识
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
if(!bFileIO && !HandleSectorIO(byBuff, sHead.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取磁盘扇区
else if(bFileIO && !FileSectorIO(byBuff, sHead.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取映象扇区
LONG nOff = OFFSET(sHead, dwValCRC32); // 取位置偏移量
sHead.dwValCRC32 = GenerateCRC32((BYTE *)(&sHead), nOff);
STcsyRegistHead TempHead = sHead; // 临时的标识头
BYTE byKeys[sizeof(DATA_KEYS)]; // 取回原加密钥
CryptXOR(byKeys, DATA_KEYS, sizeof(DATA_KEYS)); // 加密后再存贮
SckDesBin(0, (BYTE *)(&TempHead), sizeof(sHead), byKeys);
BYTE *pStart = &byBuff[sHead.AddrSelf.nByteOffs];// 数据开始地址
memcpy(pStart, &TempHead, sizeof(sHead)); // 写入真正数据
WriteNewFlag(pStart, sizeof(sHead)); // 重写首.New尾
if(!bFileIO) return (BOOL)HandleSectorIO(byBuff, // 不强制用文件
sHead.AddrSelf.dwSectNum, WRITE_SECT);
else return (BOOL)FileSectorIO(byBuff,
sHead.AddrSelf.dwSectNum, WRITE_SECT); // 强制映象文件
}
//-------------------------------------------------------------------------//
// 读取在磁盘扇区中已有的单元数据,定入映象文件(可选):要先解密
BOOL CTcsyRegistList::LoadDiskItem(STcsyRegistItem &sItem, BOOL bFileIO)
{
if(!IsValidAddr(sItem.AddrSelf)) return FALSE; // 超越扇区范围
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
if(!bFileIO && !HandleSectorIO(byBuff, sItem.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取磁盘扇区
else if(bFileIO && !FileSectorIO(byBuff, sItem.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取映象扇区
STcsyRegistItem TempItem; // 临时单元数据
memcpy(&TempItem, &byBuff[sItem.AddrSelf.nByteOffs], sizeof(sItem));
BYTE byKeys[sizeof(DATA_KEYS)]; // 取回原加密钥
CryptXOR(byKeys, DATA_KEYS, sizeof(DATA_KEYS)); // 解密后再校验
SckDesBin(1, (BYTE *)(&TempItem), sizeof(sItem), byKeys);
if(memcmp(TempItem.byItemFlag, sItem.byItemFlag, sizeof(sItem.byItemFlag)))
return FALSE; // 数据标识不符
LONG nOff = OFFSET(sItem, dwValCRC32); // 取位置偏移量
if(GenerateCRC32((BYTE *)(&TempItem), nOff) != TempItem.dwValCRC32)
return FALSE; // 校验数据失败
TempItem.AddrSelf = sItem.AddrSelf; // 修正扇区偏移
sItem = TempItem; return TRUE; // 成功提取数据
}
// 写入在磁盘扇区中已有的单元数据,无须返回数据:要再加密
BOOL CTcsyRegistList::SaveDiskItem(STcsyRegistItem sItem, BOOL bFileIO)
{
if(!IsValidAddr(sItem.AddrSelf)) return FALSE; // 超越扇区范围
BYTE byBuff[DISK_SECTOR_SIZE] = {0}; // 扇区临时缓冲
if(!bFileIO && !HandleSectorIO(byBuff, sItem.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取磁盘扇区
else if(bFileIO && !FileSectorIO(byBuff, sItem.AddrSelf.dwSectNum, READ_SECT))
return FALSE; // 读取映象扇区
STcsyRegistItem TempItem = sItem; // 临时单元数据
LONG nOff = OFFSET(TempItem, dwValCRC32); // 取位置偏移量
TempItem.dwValCRC32 = GenerateCRC32((BYTE *)(&TempItem), nOff);
BYTE byKeys[sizeof(DATA_KEYS)]; // 取回原加密钥
CryptXOR(byKeys, DATA_KEYS, sizeof(DATA_KEYS)); // 加密后再存贮
SckDesBin(0, (BYTE *)(&TempItem), sizeof(sItem), byKeys);
BYTE *pStart = &byBuff[sItem.AddrSelf.nByteOffs];// 数据开始地址
memcpy(pStart, &TempItem, sizeof(sItem)); // 写入真正数据
WriteNewFlag(pStart, sizeof(sItem)); // 重写首.New尾
if(!bFileIO) return (BOOL)HandleSectorIO(byBuff, // 不强制用文件
sItem.AddrSelf.dwSectNum, WRITE_SECT);
else return (BOOL)FileSectorIO(byBuff,
sItem.AddrSelf.dwSectNum, WRITE_SECT); // 强制映象文件
}
//-------------------------------------------------------------------------//
// 尾追数据:添加记录时用,申请新的内存。并写到新分配的扇区:加密
BOOL CTcsyRegistList::AddEnd(const STcsyRegistData *pData)
{
if(pData == NULL) return FALSE; // 入口指针为空
STcsyRegistHead TempHead = TcsyHead; // 临时注册标头
if(TempHead.nItemCount < 0) return FALSE; // 链表尚未建立
STcsyRegistData rData = *pData; // 加密注册数据
CryptXOR((BYTE *)(&rData), sizeof(rData)); // 采用.XOR方式
if(FindUserRegist(rData.byProductNum) == TRUE) return TRUE;
STcsyRegistNode *pNode = new STcsyRegistNode; // 新的内存节点
if(pNode == NULL) return FALSE; // 申请内存失败
BOOL bEmptyList = FALSE; // 是否是空链表
STcsyRegistItem bEndItem, TempItem; // 临时单元数据
if(New(TempItem.AddrSelf, sizeof(TempItem)) == FALSE)
{delete pNode; return FALSE;} // 申请新扇偏移
TempItem.RegData = rData; // 使其变成已有
if(TempHead.nItemCount == 0) // 还没有单元区
{
bEmptyList = TRUE;
TempHead.AddrStart = TempHead.AddrEnd = TempItem.AddrSelf;
}
else // 已有注册数据
{
STcsyRegistItem tEndItem = PtrEnd->ItemData; // 处理尾部单元
TempItem.AddrPrior = tEndItem.AddrSelf;
tEndItem.AddrNext = TempItem.AddrSelf;
TempHead.AddrEnd = TempItem.AddrSelf;
if(SaveDiskItem(tEndItem) == FALSE) // 存新的尾单元
{
Delete(TempItem.AddrSelf);
delete pNode; return FALSE;
}
bEndItem = PtrEnd->ItemData; // 写尾内存数据
PtrEnd->ItemData = tEndItem;
}
TempHead.nItemCount++; // 多了一个成员
if(!SaveDiskItem(TempItem) || !SaveDiskHead(TempHead))
{
if(!bEmptyList) SaveDiskItem(bEndItem); // 恢复原尾节点
Delete(TempItem.AddrSelf);
if(!bEmptyList) PtrEnd->ItemData = bEndItem;
delete pNode; return FALSE; // 写入扇区失败
}
TcsyHead = TempHead; // 记录新的标头
m_nNodeCount++; // 多了一个成员
pNode->ItemData = TempItem; // 拷贝到新内存
if(PtrEnd == NULL) // 当前为一空链
{
PtrStart = PtrEnd = PtrCurr = pNode; // 内存首尾指针
}
else
{
pNode->PtrPrior = PtrEnd; // 新节点上节点
PtrEnd->PtrNext = pNode; // 原尾的下节点
PtrEnd = PtrCurr = pNode; // 新尾和新当前
}
return TRUE; // 返回成功追加
}
// 尾追单元:装载时用,读取原扇区,并写到新申请的内存,返回上下单元偏移
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -