unit mEncryptUnit; interface uses Windows, SysUtils, Forms, Classes, ScUtils; const // SafeNet(彩虹)SoftDog(软件狗) DT_SN_SD = 5; // 飞天R1 DT_FT_R1 = 6; CS_Error = -5; CS_NeedAuthorize = -4; CS_NoDog = -3; CS_DogTypeError = -2; CS_VerifyError = -1; CS_Ignore = 0; CS_Success = 1; CS_WantAuthorize = 2; CS_NeedUpdate = -6; CS_EndDate = -7; CS_CloseToLimitDate = -8; // 0:因某些原因(如加密够忙)而忽略检查,-1:加密检查错误,-2:狗类型不正确;1:清单狗,2:预算狗 function CheckDog: Integer; function CheckDog1: Integer; function SimpleCheck: Boolean; function CheckTimes(AIsOnOpen: Boolean = False): Integer; function CheckHours: Integer; function CheckEdition: Integer; function CheckLimitDate: Integer; function CheckData: Integer; function CheckDogAndHint: Boolean; function DelayCheckDog: Boolean; function CheckDogErrorCountAndHint: Boolean; function GetReportOprList: TStrings; function GetReportOprNum(AOpr: string): Integer; procedure ClearReportOprList; function GetReportFuncList: TStrings; function GetReportFuncNum(AOpr: string): Integer; procedure ClearReportFuncList; procedure DogError; function DogIsBusy: Boolean; function OpenDog: Integer; procedure SaveDog; function UserAuthorize(AAuthorize: array of Byte): Boolean; function UserUpdateLock(AUpdateData: array of Byte): Boolean; function EncryptKey: string; function AuthorizeKey: string; // 是否受限版固化清单 function IsLimitedFixedBills: Boolean; // 能否打开固化清单项目(学习版、网络版、标准版) function CanOpenFixedBills: Boolean; var strHASPID: string; bAuthorized: Boolean = True; Activations: Integer; StartTime, RunTime, LastTime: LongWord; EncryptLog: TStringList; // 保存当前打开的所有项目 EvtSaveAll: TInternalEvent; // 加密锁版本号 _DogEdition: Byte = 0; procedure CreateEncryptLog; procedure AddEncryptLog(ALog: string); implementation uses Math, CommonMessages, ScConfig, CryptUtils, mEncryptPwd, mSNSEncrypt, mR1Encrypt, mEncryptEditions; const MutexAddressName = 'SmartCost_Mutex_Address_Name'; var DogErrorCount: Integer; MutexHandle: THandle; ReportOprList: TStringList = nil; ReportFuncList: TStringList = nil; // 需要记录加密日志的话,改为TRUE; // 目前仅为深思网络版写了记录日志的代码 function NeedLog: Boolean; begin Result := ConfigInfo.IsWriteEncryptLog; end; procedure CreateEncryptLog; begin EncryptLog := TStringList.Create; end; procedure AddEncryptLog(ALog: string); begin if (EncryptLog <> nil) and NeedLog then EncryptLog.Add(ALog); end; procedure FreeAndSaveEncryptLog; begin if EncryptLog <> nil then begin if NeedLog then EncryptLog.SaveToFile(ExtractFilePath(Application.ExeName) + 'EncryptLog.log'); FreeAndNil(EncryptLog); end; end; function EncryptKey: string; var arrResult: array of Byte; iOutputLength: Integer; begin iOutputLength := GetOutputLength(ScEncryptKey); SetLength(arrResult, iOutputLength); Decrypt_Simple(ScEncryptKey, Length(ScEncryptKey), arrResult, iOutputLength); SetString(Result, PChar(@arrResult[0]), iOutputLength); end; function AuthorizeKey: string; var arrResult: array of Byte; iOutputLength: Integer; begin iOutputLength := GetOutputLength(ScAuthorizeKey); SetLength(arrResult, iOutputLength); Decrypt_Simple(ScAuthorizeKey, Length(ScAuthorizeKey), arrResult, iOutputLength); SetString(Result, PChar(@arrResult[0]), iOutputLength); end; function DogIsBusy: Boolean; var WaitFlag: DWORD; begin if MutexHandle = 0 then begin Result := False; Exit; end; WaitFlag := WaitForSingleObject(MutexHandle, 0); Result := (WaitFlag <> WAIT_OBJECT_0) and (WaitFlag <> WAIT_ABANDONED); end; function SimpleCheck: Boolean; var iPort: Integer; begin Result := False; if SimpleR1Check = DT_FT_R1 then begin DogType := DT_FT_R1; Result := True; end; if (not Result) and (SimpleSNSCheck = DT_SN_SD) then begin DogType := DT_SN_SD; Result := True; end; AddEncryptLog('[S] SimpleCheck: DogType = ' + IntToStr(DogType)); end; function CheckTimes(AIsOnOpen: Boolean): Integer; begin Result := CS_Error; case DogType of DT_FT_R1: Result := CheckR1Times(AIsOnOpen); DT_SN_SD: Result := CheckSNSTimes(AIsOnOpen); end; end; function CheckHours: Integer; begin Result := CS_Error; case DogType of DT_FT_R1: Result := CheckR1Hours; DT_SN_SD: Result := CheckSNSHours; end; end; function CheckLimitDate: Integer; begin Result := CS_Error; case DogType of DT_FT_R1: Result := CheckR1LimitDate; DT_SN_SD: Result := CheckSNSLimitDate else Result := CS_Ignore; end; end; function CheckEdition: Integer; begin Result := CS_Error; SimpleCheck; case DogType of DT_FT_R1: Result := CheckR1Edition; DT_SN_SD: Result := CheckSNSEdition; end; {$IFDEF _ScYS2007} if Result >= 0 then case DogType of DT_FT_R1: Result := CheckR1AdditionEdition; DT_SN_SD: Result := CheckSNSAdditionEdition; end; {$ENDIF} end; function CheckData: Integer; begin Result := CS_NoDog; SimpleCheck; case DogType of DT_FT_R1: Result := CheckR1Data; DT_SN_SD: Result := CheckSNSData; end; end; function CheckDog1: Integer; begin Result := Checkdog; end; function CheckDog: Integer; var iResult: Integer; begin {$IFDEF _ScInternal} Result := CS_Ignore; {$ELSE} if DogIsBusy then begin Result := CS_Ignore; Exit; end; try Result := CheckData; if (Result = CS_Ignore) or (Result = CS_Success) then begin iResult := CheckLimitDate; if iResult = CS_EndDate then Result := iResult; end; finally ReleaseMutex(MutexHandle); end; {$ENDIF} end; function DelayCheckDog: Boolean; begin Result := True; case CheckDog of CS_VerifyError, CS_DogTypeError, CS_Error, CS_NoDog, CS_NeedAuthorize: begin Inc(DogErrorCount); if DogErrorCount > 2 then Result := False; end; end; end; function GetReportOprList: TStrings; begin if not Assigned(ReportOprList) then ReportOprList := TStringList.Create; Result := ReportOprList; end; procedure ClearReportOprList; var iCheckData: Integer; begin case DogType of DT_FT_R1, DT_SN_SD: GetReportOprList.Clear; end; end; function GetReportOprNum(AOpr: string): Integer; begin Result := -1; case DogType of DT_FT_R1: Result := GetR1ReportOprNum(AOpr); DT_SN_SD: Result := GetSNSReportOprNum(AOpr); end; end; function GetReportFuncList: TStrings; begin if not Assigned(ReportFuncList) then ReportFuncList := TStringList.Create; Result := ReportFuncList; end; procedure ClearReportFuncList; var iCheckData: Integer; begin case DogType of DT_FT_R1, DT_SN_SD: GetReportFuncList.Clear; end; end; function GetReportFuncNum(AOpr: string): Integer; begin Result := -1; case DogType of DT_FT_R1: Result := GetR1ReportFuncNum(AOpr); DT_SN_SD: Result := GetSNSReportFuncNum(AOpr); end; end; procedure DogError; begin CommonMessage(pmtError, [pmbOk], '没有检查到加密锁,或加密锁类型不正确。'#13#10'请购买正版SmartCost。' + #13#10'如果插上加密锁后仍有问题,请拨打产品注册电话:' + LoadAuthorizePhone + '。'); if Assigned(EvtSaveAll) then begin EvtSaveAll; EvtSaveAll := nil; end; Application.Terminate; end; procedure DogVerifyError; begin CommonMessage(pmtError, [pmbOk], '没有检查到加密锁。'#13#10'请购买正版SmartCost。' + #13#10'如果插上加密锁后仍有问题,请拨打产品注册电话:' + LoadAuthorizePhone + '。'); Application.Terminate; end; procedure DogTypeError; begin CommonMessage(pmtError, [pmbOk], '加密锁类型不正确,请检查。' + #13#10'如果插上正确的加密锁后仍有问题,请拨打产品注册电话:' + LoadAuthorizePhone + '。'); Application.Terminate; end; procedure DogEndDate; begin CommonMessage(pmtError, [pmbOk], '加密锁使用时间限制已到。' + #13#10'如果需延长使用时间,请与客服中心联系。'); Application.Terminate; end; function CheckDogAndHint: Boolean; begin Result := True; case CheckDog of CS_Error: begin DogError; Result := False; end; CS_NoDog: begin DogError; Result := False; end; CS_NeedAuthorize: begin DogVerifyError; Result := False; end; CS_VerifyError: begin DogVerifyError; Result := False; end; CS_DogTypeError: begin DogTypeError; Result := False; end; CS_EndDate: begin DogEndDate; Result := False; end; end; end; function CheckDogErrorCountAndHint: Boolean; begin Result := True; if DogErrorCount > 2 then begin DogError; Result := False; end; end; procedure CreateDogMutex; var SA: TSecurityAttributes; begin SA.nLength := SizeOf(SA); SA.lpSecurityDescriptor := nil; SA.bInheritHandle := False; MutexHandle := CreateMutex(@SA, False, PChar(MutexAddressName)); end; function OpenDog: Integer; var iCheckResult1, iCheckresult2, iEditionResult, iLimitDate: Integer; begin Result := CS_NoDog; if DogIsBusy then begin Result := CS_Ignore; Exit; end; try SimpleCheck; StartTime := GetTickCount; if DogType in [DT_FT_R1, DT_SN_SD] then StartTime := StartTime div 1000; if (CheckData in [CS_Success, CS_Ignore]) then begin iEditionResult := CheckEdition; if iEditionResult < 0 then begin if iEditionResult = CS_NeedUpdate then Result := CS_NeedUpdate else Result := CS_DogTypeError; end else begin iCheckResult1 := CheckHours; iCheckResult2 := CheckTimes(True); iLimitDate := CheckLimitDate; if iLimitDate = CS_Success then Result := iLimitDate else if iLimitDate = CS_CloseToLimitDate then Result := iLimitDate else if iLimitDate = CS_EndDate then begin Result := iLimitDate; Exit; end else if iLimitDate = CS_Ignore then begin if (iCheckResult1 = CS_NeedAuthorize) or (iCheckResult2 = CS_NeedAuthorize) then Result := CS_NeedAuthorize else if (iCheckResult1 = CS_WantAuthorize) or (iCheckResult1 = CS_WantAuthorize) then Result := CS_WantAuthorize else Result := CS_Success; end; end; end; if not ((Result = CS_Success) or (Result = CS_WantAuthorize) or (Result = CS_NeedAuthorize) or (Result = CS_Ignore) or (Result = CS_NeedUpdate) or (Result = CS_CloseToLimitDate)) then Exit; case DogType of DT_FT_R1: if OpenR1Dog <> CS_Success then Result := CS_Error; DT_SN_SD: if OpenSNSDog <> CS_Success then Result := CS_Error; end; finally ReleaseMutex(MutexHandle); end; end; procedure SaveDog; begin case DogType of DT_FT_R1: SaveR1Dog; DT_SN_SD: SaveSNSDog; end; FreeAndSaveEncryptLog; end; function UserAuthorize(AAuthorize: array of Byte): Boolean; begin Result := False; case DogType of DT_FT_R1: Result := R1UserAuthorize(AAuthorize); DT_SN_SD: Result := SNSUserAuthorize(AAuthorize); end; end; function UserUpdateLock(AUpdateData: array of Byte): Boolean; begin Result := False; case DogType of DT_FT_R1: Result := R1UserUpdateLock(AUpdateData); DT_SN_SD: Result := SNSUserUpdateLock(AUpdateData); end; end; // 是否受限版固化清单 function IsLimitedFixedBills: Boolean; begin Result := _DogEdition in [eidLimitedFixBills]; end; // 能否打开固化清单项目 function CanOpenFixedBills: Boolean; begin Result := not (_DogEdition in [0, eidStandard]); end; initialization DogErrorCount := 0; CreateDogMutex; finalization CloseHandle(MutexHandle); MutexHandle := 0; end.