mR1Encrypt.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. unit mR1Encrypt;
  2. interface
  3. uses
  4. Windows, SysUtils, Forms, Classes;
  5. type
  6. ER1Error = class(Exception);
  7. function SimpleR1Check: Integer;
  8. function CheckR1Times(AIsOnOpen: Boolean = False): Integer;
  9. function CheckR1Hours: Integer;
  10. function CheckR1AdditionEdition: Integer;
  11. function CheckR1Edition(AOpening: Boolean = False): Integer;
  12. function CheckR1Data: Integer;
  13. function CheckR1LimitDate: Integer;
  14. function GetR1ReportOprNum(AOpr: string): Integer;
  15. function GetR1ReportFuncNum(AOpr: string): Integer;
  16. function OpenR1Dog: Integer;
  17. procedure SaveR1Dog;
  18. function R1UserAuthorize(AAuthorize: array of Byte): Boolean;
  19. function R1UserUpdateLock(AUpdateData: array of Byte): Boolean;
  20. implementation
  21. uses
  22. Math, CommonMessages, ScUtils, mEncryptPWD, CryptUtils, ScConfig,
  23. mEncryptUnit, mEncryptTypes, mEncryptEditions, Rockey1,
  24. PHPWebDm;
  25. const
  26. _R1_Key: array [0..16] of Byte = ($00, $00, $00, $0D, $CE, $CE, $CD, $CF, $8C, $8B, $BC, $90, $8D, $8B, $92, $9E, $AC);
  27. _R1_PID: array [0..11] of Byte = ($00, $00, $00, $08, $06, $71, $23, $3D, $53, $05, $0A, $78);
  28. _R1_UserPin: array [0..19] of Byte = ($00, $00, $00, $10, $39, $EF, $50, $6B, $41, $0D, $CC, $52, $39, $EF, $50, $6B, $41, $0D, $CC, $52);
  29. var
  30. _R1DogHandle: THandle = 0;
  31. _R1DogOpened: Boolean = False;
  32. _R1_HID: array [0..15] of Byte;
  33. function DecryptKey: string;
  34. var
  35. arrResult: array of Byte;
  36. iOutputLength: Integer;
  37. begin
  38. iOutputLength := GetOutputLength(_R1_Key);
  39. SetLength(arrResult, iOutputLength);
  40. Decrypt_Simple(_R1_Key, Length(_R1_Key), arrResult, iOutputLength);
  41. SetString(Result, PChar(@arrResult[0]), iOutputLength);
  42. end;
  43. function DecryptValues(AInput: array of Byte; ALength: Integer; var AOutput: array of Byte): Integer;
  44. var
  45. pKey: Pointer;
  46. begin
  47. pKey := nil;
  48. Decrypt_BlowFish(DecryptKey, @AInput[0], ALength, pKey, Result);
  49. CopyMemory(@AOutput[0], pKey, Result);
  50. end;
  51. function DecryptPID(var AOutput: array of Byte): Integer;
  52. begin
  53. Result := DecryptValues(_R1_PID, Length(_R1_PID), AOutput);
  54. end;
  55. function DecryptUserPin(var AOutput: array of Byte): Integer;
  56. begin
  57. Result := DecryptValues(_R1_UserPin, Length(_R1_UserPin), AOutput);
  58. end;
  59. procedure InnerCloseR1Dog;
  60. begin
  61. if _R1DogOpened then
  62. begin
  63. R1_Close(_R1DogHandle);
  64. end;
  65. end;
  66. procedure InnerOpenR1Dog;
  67. var
  68. I: Integer;
  69. iResult: Cardinal;
  70. iCount: DWORD;
  71. aPID: array [0..7] of Byte;
  72. aUserPin: array [0..16] of Byte;
  73. iTryCount: Byte;
  74. begin
  75. if _R1DogOpened then Exit;
  76. // 如果是插的彩虹锁,飞天锁驱动函数R1_Find没对iCount初始化,搞得循环2亿多次。现在先初始化iCount就可以了。
  77. iCount := 0;
  78. // 查找狗
  79. iResult := R1_Find(nil, @iCount);
  80. if iResult <> 0 then
  81. Exit;
  82. if iCount = 0 then
  83. Exit;
  84. // 解出PID
  85. if DecryptPID(aPID) = 0 then
  86. Exit;
  87. // 解出用户密码
  88. if DecryptUserPin(aUserPin) = 0 then
  89. Exit;
  90. // 不知为什么在win7 32位下,必须加一个0字符才能正确执行。可能跟C要求字符串以0字符结尾有关
  91. aUserPin[16] := 0;
  92. for I := 0 to iCount - 1 do
  93. begin
  94. // 获取句柄
  95. iResult := R1_Open(@_R1DogHandle, @aPID[0], I);
  96. if iResult <> 0 then
  97. Continue;
  98. // 验证
  99. iResult := R1_VerifyUserPin(_R1DogHandle, @aUserPin[0], @iTryCount);
  100. if iResult <> 0 then
  101. Continue;
  102. // 判断一下版本才决定是否正确的锁
  103. if CheckR1Edition(True) = CS_Success then
  104. begin
  105. _R1DogOpened := True;
  106. Break;
  107. end
  108. else
  109. InnerCloseR1Dog;
  110. end;
  111. end;
  112. const R1EncryptVer = 1;
  113. function SimpleR1Check: Integer;
  114. var
  115. iResult: Cardinal;
  116. aData: array [0..15] of Byte;
  117. iLength: WORD;
  118. begin
  119. Result := -1;
  120. InnerOpenR1Dog;
  121. if not _R1DogOpened then Exit;
  122. iResult := R1_Read(_R1DogHandle, 0, 3, @aData[0], @iLength, MEM_PRI);
  123. if (iResult = 0) and (aData[2] = R1EncryptVer) then
  124. Result := DT_FT_R1;
  125. end;
  126. function CheckR1Times(AIsOnOpen: Boolean): Integer;
  127. var
  128. iResult: Cardinal;
  129. aData: array [0..11] of Byte;
  130. iTimes, iRunTimes, iLength: Word;
  131. begin
  132. Result := CS_Error;
  133. if SimpleR1Check < 0 then
  134. Exit;
  135. // 允许次数
  136. iTimes := 0;
  137. ZeroMemory(@aData[0], Length(aData));
  138. // 实际是$07-$08,为迷惑,取$03-$0E
  139. iResult := R1_Read(_R1DogHandle, $03, Length(aData), @aData[0], @iLength, MEM_PRI);
  140. if iResult = 0 then
  141. iTimes := aData[4] shl 8 + aData[5];
  142. if iTimes = 0 then
  143. Exit;
  144. if iTimes = $FFFF then
  145. begin
  146. Result := CS_Success;
  147. Exit;
  148. end;
  149. bAuthorized := False;
  150. // 实际次数
  151. iRunTimes := 0;
  152. ZeroMemory(@aData[0], Length(aData));
  153. // 实际是$04-$05,为迷惑,取$02-$0D
  154. iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PUB);
  155. if iResult = 0 then
  156. iRunTimes := aData[2] shl 8 + aData[3];
  157. Activations := iRunTimes;
  158. if AIsOnOpen then
  159. begin
  160. if iRunTimes >= iTimes then
  161. Result := CS_NeedAuthorize
  162. else
  163. Result := CS_WantAuthorize;
  164. end
  165. else
  166. begin
  167. if iRunTimes > iTimes then
  168. Result := CS_NeedAuthorize
  169. else
  170. Result := CS_WantAuthorize;
  171. end;
  172. end;
  173. function CheckR1Hours: Integer;
  174. var
  175. iResult: Cardinal;
  176. aData: array [0..11] of Byte;
  177. iSeconds, iRunSeconds: Cardinal;
  178. iLength: Word;
  179. begin
  180. Result := CS_Error;
  181. if SimpleR1Check < 0 then
  182. Exit;
  183. // 允许时间
  184. iSeconds := 0;
  185. ZeroMemory(@aData[0], Length(aData));
  186. // 实际是$03-$06,为迷惑,取$02-$0D
  187. iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PRI);
  188. if iResult = 0 then
  189. iSeconds := ((aData[1] shl 8 + aData[2]) shl 8 + aData[3]) shl 8 + aData[4];
  190. // iRunSeconds := ((aData[5] shl 8 + aData[6]) shl 8 + aData[7]) shl 8 + aData[8];
  191. if iSeconds = 0 then
  192. Exit;
  193. if iSeconds = $FFFFFFFF then
  194. begin
  195. Result := CS_Success;
  196. Exit;
  197. end;
  198. bAuthorized := False;
  199. // 实际运行时间
  200. iRunSeconds := 0;
  201. ZeroMemory(@aData[0], Length(aData));
  202. // 实际是$00-$03,为迷惑,取$00-$0C
  203. iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PUB);
  204. if iResult = 0 then
  205. iRunSeconds := ((aData[0] shl 8 + aData[1]) shl 8 + aData[2]) shl 8 + aData[3];
  206. LastTime := iRunSeconds;
  207. if iRunSeconds > iSeconds then
  208. Result := CS_NeedAuthorize
  209. else
  210. Result := CS_WantAuthorize;
  211. end;
  212. function CheckR1LimitDate: Integer;
  213. var
  214. iResult: Cardinal;
  215. aData: array [0..11] of Byte;
  216. iType: Byte;
  217. iUserDate, iLimitDate: Cardinal;
  218. fDate, fCompileDate: TDateTime;
  219. iLength: Word;
  220. begin
  221. Result := CS_Error;
  222. if SimpleR1Check < 0 then
  223. Exit;
  224. // 加密类型是否时间限制狗
  225. ZeroMemory(@aData[0], Length(aData));
  226. // 实际是$63,为迷惑,取$5B-$66
  227. iResult := R1_Read(_R1DogHandle, $5B, Length(aData), @aData[0], @iLength, MEM_PRI);
  228. if iResult <> 0 then Exit;
  229. if aData[8] <> Ord(etDate) then
  230. begin
  231. Result := CS_Ignore;
  232. Exit;
  233. end;
  234. bAuthorized := False;
  235. // 允许日期
  236. iLimitDate := 0;
  237. ZeroMemory(@aData[0], Length(aData));
  238. // 实际是$09-$0C,为迷惑,取$05-$10
  239. iResult := R1_Read(_R1DogHandle, $05, Length(aData), @aData[0], @iLength, MEM_PRI);
  240. if iResult = 0 then
  241. iLimitDate := ((aData[4] shl 8 + aData[5]) shl 8 + aData[6]) shl 8 + aData[7];
  242. // 运行日期
  243. iUserDate := 0;
  244. ZeroMemory(@aData[0], Length(aData));
  245. // 实际是$06-$09,为迷惑,取$05-$10
  246. iResult := R1_Read(_R1DogHandle, $05, Length(aData), @aData[0], @iLength, MEM_PUB);
  247. if iResult = 0 then
  248. iUserDate := ((aData[1] shl 8 + aData[2]) shl 8 + aData[3]) shl 8 + aData[4];
  249. fDate := PHPWeb.SystemDateTime;
  250. fCompileDate := CompileDateTime;
  251. if fCompileDate > iLimitDate then
  252. begin
  253. Result := CS_EndDate;
  254. Exit;
  255. end;
  256. if fDate > iLimitDate then
  257. Result := CS_EndDate
  258. else if iLimitDate - fDate < 7 then
  259. Result := CS_CloseToLimitDate
  260. else
  261. Result := CS_Success;
  262. end;
  263. function CheckR1AdditionEdition: Integer;
  264. var
  265. iResult: Cardinal;
  266. aData: array [0..15] of Byte;
  267. iLength: Word;
  268. begin
  269. Result := CS_NoDog;
  270. if SimpleR1Check < 0 then
  271. Exit;
  272. // 附加版本限制
  273. ZeroMemory(@aData[0], Length(aData));
  274. // 实际是$70-$72,为迷惑,取$70-$7F
  275. iResult := R1_Read(_R1DogHandle, $70, Length(aData), @aData[0], @iLength, MEM_PRI);
  276. if iResult = 0 then
  277. begin
  278. if aData[1] = $16 then
  279. Result := CS_Success
  280. else
  281. Result := CS_NeedUpdate;
  282. end;
  283. end;
  284. function CheckR1Edition(AOpening: Boolean): Integer;
  285. var
  286. iResult: Cardinal;
  287. aData: array [0..255] of Byte;
  288. iEdition: Byte;
  289. iLength: Word;
  290. I: Integer;
  291. begin
  292. Result := CS_NoDog;
  293. if (not AOpening) and (SimpleR1Check < 0) then
  294. Exit;
  295. // 附加版本限制
  296. iEdition := 0;
  297. ZeroMemory(@aData[0], Length(aData));
  298. // 实际是$01,为迷惑,取$00-$FE
  299. iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PRI);
  300. if iResult = 0 then
  301. iEdition := aData[1]
  302. else
  303. Exit;
  304. if iEdition = 0 then
  305. Exit;
  306. DogEdition := iEdition;
  307. if CheckEncryptEdition(iEdition) then
  308. Result := CS_Success
  309. else
  310. Result := CS_DogTypeError;
  311. if Result = CS_Success then
  312. begin
  313. _DogEdition := iEdition;
  314. // 如果是固话清单限制版,则不退出,继续后面的检查
  315. {$IFNDEF _mEncrypt}
  316. if not iEdition in [eidLimitedFixBills] then
  317. Exit;
  318. {$ENDIF}
  319. end;
  320. // 读取附加版本ID
  321. ZeroMemory(@aData[0], Length(aData));
  322. // 实际是$80-$92,为迷惑,取$77-$175
  323. iResult := R1_Read(_R1DogHandle, $77, Length(aData), @aData[0], @iLength, MEM_PRI);
  324. if iResult <> 0 then Exit;
  325. for I := Low(aData) + 9 to High(aData) do
  326. begin
  327. iEdition := aData[I];
  328. if iEdition = 0 then Break;
  329. if CheckEncryptEdition(iEdition) then
  330. begin
  331. Result := CS_Success;
  332. _DogEdition := iEdition;
  333. // 如果附加版本是固化清单限制版,则不跳出循环,以便检查是否还有固化清单完整版
  334. if iEdition = eidLimitedFixBills then
  335. Continue;
  336. // 如果是计量支付需要检测所有的功能模块,则在检测到所有功能模块可用前,不可跳出循环
  337. {$IFDEF _mEncrypt}
  338. if not (_bHasCompileEdition and _bHasMeasureEdition and _bHasPlanEdition) then
  339. Continue;
  340. {$ENDIF}
  341. Break;
  342. end;
  343. end;
  344. end;
  345. function CheckR1Data: Integer;
  346. var
  347. iResult: Cardinal;
  348. iCheckData, iOutputLength: Integer;
  349. pKey: Pointer;
  350. arrKey: array [0..15] of Byte;
  351. arrData: array [0..19] of Byte;
  352. I: Integer;
  353. bIsZero: Boolean;
  354. iLength: Word;
  355. begin
  356. Result := CS_NoDog;
  357. if SimpleR1Check < 0 then
  358. Exit;
  359. // HID
  360. ZeroMemory(@_R1_HID[0], Length(_R1_HID));
  361. iResult := R1_GetHID(_R1DogHandle, @_R1_HID[0]);
  362. if iResult <> 0 then Exit;
  363. strHaspID := '';
  364. // 注意此处与其他狗不同
  365. for I := 0 to Length(_R1_HID) - 1 do
  366. strHaspID := strHaspID + Char(_R1_HID[I]);
  367. Randomize;
  368. iCheckData := RandomRange(11000, 11050);
  369. case iCheckData of
  370. 11011..11020:
  371. begin
  372. Result := CS_Ignore;
  373. Exit;
  374. end;
  375. end;
  376. // 校验码
  377. ZeroMemory(@arrKey[0], Length(arrKey));
  378. ZeroMemory(@arrData[0], Length(arrData));
  379. // $10-$23
  380. iResult := R1_Read(_R1DogHandle, $10, Length(arrData), @arrData[0], @iLength, MEM_PRI);
  381. if iResult = 0 then
  382. begin
  383. pKey := nil;
  384. try
  385. Decrypt_BlowFish(EncryptKey, @arrData[0], 20, pKey, iOutputLength);
  386. CopyMemory(@arrKey[0], pKey, iOutputLength);
  387. finally
  388. if Assigned(pKey) then
  389. FreeMem(pKey);
  390. end;
  391. end;
  392. for I := 0 to Length(_R1_HID) - 1 do
  393. begin
  394. if _R1_HID[I] <> arrKey[I] then
  395. begin
  396. Result := CS_VerifyError;
  397. Exit;
  398. Break;
  399. end;
  400. end;
  401. Result := CS_Success;
  402. end;
  403. function GetR1ReportOprNum(AOpr: string): Integer;
  404. const
  405. OprStr = '[,-,*,^,:=,/,p,<,<=,>=,>,+,<>,=,or,!=,and,f';
  406. var
  407. iResult: Cardinal;
  408. OprStrs: TStringList;
  409. StrIndex: Integer;
  410. OprNum: Byte;
  411. aData: array [0..19] of Byte;
  412. iLength: Word;
  413. begin
  414. Result := -1;
  415. StrIndex := GetReportOprList.IndexOf(AOpr);
  416. if StrIndex > -1 then
  417. begin
  418. Result := Integer(GetReportOprList.Objects[StrIndex]);
  419. end
  420. else
  421. begin
  422. OprStrs := TStringList.Create;
  423. try
  424. OprStrs.CommaText := OprStr;
  425. iResult := R1_Read(_R1DogHandle, $30, Length(aData), @aData[0], @iLength, MEM_PRI);
  426. if iResult = 0 then
  427. begin
  428. StrIndex := OprStrs.IndexOf(AOpr);
  429. if StrIndex >= 0 then
  430. begin
  431. OprNum := aData[StrIndex];
  432. GetReportOprList.AddObject(AOpr, Pointer(OprNum));
  433. Result := OprNum;
  434. end;
  435. end;
  436. finally
  437. OprStrs.Free;
  438. end;
  439. end;
  440. end;
  441. function GetR1ReportFuncNum(AOpr: string): Integer;
  442. const
  443. FuncStr = 'sql,treechapterinsert,getindex,addnull,shrink,copy,'+
  444. 'sorttreechapter,joindata,chapterinsert,'+
  445. 'refcopy,count,refcopyex1';
  446. var
  447. iResult: Cardinal;
  448. FuncStrs: TStringList;
  449. StrIndex: Integer;
  450. OprNum: Byte;
  451. aData: array [0..19] of Byte;
  452. iLength: Word;
  453. begin
  454. Result := -1;
  455. StrIndex := GetReportFuncList.IndexOf(AOpr);
  456. if StrIndex > -1 then
  457. begin
  458. Result := Integer(GetReportFuncList.Objects[StrIndex]);
  459. end
  460. else
  461. begin
  462. FuncStrs := TStringList.Create;
  463. try
  464. FuncStrs.CommaText := FuncStr;
  465. iResult := R1_Read(_R1DogHandle, $50, Length(aData), @aData[0], @iLength, MEM_PRI);
  466. if iResult = 0 then
  467. begin
  468. StrIndex := FuncStrs.IndexOf(AOpr);
  469. if StrIndex >= 0 then
  470. begin
  471. OprNum := aData[StrIndex];
  472. GetReportFuncList.AddObject(AOpr, Pointer(900 + OprNum));
  473. Result := 900 + OprNum;
  474. end;
  475. end;
  476. finally
  477. FuncStrs.Free;
  478. end;
  479. end;
  480. end;
  481. function OpenR1Dog: Integer;
  482. var
  483. iResult: Cardinal;
  484. aData: array [0..11] of Byte;
  485. iTimes, iLength: Word;
  486. begin
  487. Result := CS_Error;
  488. // 打开狗则运行次数立刻+1
  489. // 实际是$04-$05为迷惑,取$02-$0D
  490. iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PUB);
  491. if iResult = 0 then
  492. begin
  493. iTimes := aData[2] shl 8 + aData[3];
  494. end
  495. else
  496. Exit;
  497. iTimes := iTimes + 1;
  498. ZeroMemory(@aData[0], Length(aData));
  499. aData[0] := iTimes shr 8;
  500. aData[1] := iTimes and $00FF;
  501. iResult := R1_Write(_R1DogHandle, $04, 2, @aData[0], @iLength, MEM_PUB);
  502. if iResult <> 0 then
  503. Exit;
  504. Result := CS_Success;
  505. end;
  506. procedure SaveR1Dog;
  507. var
  508. iResult: Cardinal;
  509. aData: array [0..11] of Byte;
  510. aSecData: array [0..3] of Byte;
  511. iLastTime, iRunSeconds: LongWord;
  512. iBytesReturned: Cardinal;
  513. iLength: Word;
  514. begin
  515. RunTime := GetTickCount div 1000;
  516. if RunTime < StartTime then
  517. begin
  518. iLastTime := High(LongWord) div 1000 + RunTime - StartTime;
  519. end
  520. else
  521. iLastTime := RunTime - StartTime;
  522. // 实际是$00-$03,为迷惑,取$00-$0B
  523. iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PUB);
  524. if iResult = 0 then
  525. begin
  526. iRunSeconds := ((aData[$08] shl 8 + aData[$09]) shl 8 + aData[$0A]) shl 8 + aData[$0B];
  527. iLastTime := iLastTime + iRunSeconds;
  528. aSecData[$00] := iLastTime shr 24;
  529. aSecData[$01] := (iLastTime shr 16) and $00FF;
  530. aSecData[$02] := (iLastTime and $0000FFFF) shr 8;
  531. aSecData[$03] := iLastTime and $000000FF;
  532. iResult := R1_Write(_R1DogHandle, $00, 4, @aSecData[0], @iLength, MEM_PUB);
  533. end;
  534. end;
  535. function _R1UserAuthorize30(AAuthorize: array of Byte; ALength: Word): Boolean;
  536. var
  537. iResult: DWORD;
  538. arrUpdateFile: array [0..9999] of Byte;
  539. begin
  540. Result := False;
  541. if _R1DogOpened then
  542. begin
  543. CopyMemory(@arrUpdateFile[0], @AAuthorize[0], ALength);
  544. iResult := R1_Update(_R1DogHandle, @arrUpdateFile[0], ALength);
  545. if iResult <> 0 then
  546. raise Exception.Create(Format('Can not update, error = %d', [iResult]));
  547. Result := True;
  548. bAuthorized := True;
  549. end;
  550. end;
  551. function R1UserAuthorize(AAuthorize: array of Byte): Boolean;
  552. var
  553. pHead: PAuthFileHead;
  554. Key: array [0..9999] of Byte;
  555. iPos: Integer;
  556. begin
  557. Result := False;
  558. iPos := SizeOf(TAuthFileHead);
  559. New(pHead);
  560. try
  561. CopyMemory(pHead, @AAuthorize[0], iPos);
  562. if SameText(pHead^.FileInfo, SAuthFileInfo) and (pHead^.Version = SAuthFileVer) then
  563. begin
  564. CopyMemory(@Key[0], @AAuthorize[iPos], pHead^.Length);
  565. Result := _R1UserAuthorize30(Key, pHead^.Length);
  566. end;
  567. finally
  568. Dispose(pHead);
  569. end;
  570. end;
  571. function R1UserUpdateLock(AUpdateData: array of Byte): Boolean;
  572. var
  573. pHead: PAuthFileHead;
  574. Key: array [0..9999] of Byte;
  575. iPos: Integer;
  576. begin
  577. Result := False;
  578. iPos := SizeOf(TAuthFileHead);
  579. New(pHead);
  580. try
  581. CopyMemory(pHead, @AUpdateData[0], iPos);
  582. if SameText(pHead^.FileInfo, SUpdateFileInfo) and (pHead^.Version = SUpdateFileVer) then
  583. begin
  584. CopyMemory(@Key[0], @AUpdateData[iPos], pHead^.Length);
  585. Result := _R1UserAuthorize30(Key, pHead^.Length);
  586. end;
  587. finally
  588. Dispose(pHead);
  589. end;
  590. end;
  591. initialization
  592. finalization
  593. InnerCloseR1Dog;
  594. end.