mS4Utils.pas 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. unit mS4Utils;
  2. interface
  3. uses
  4. {$IFDEF _ScNet}
  5. S4Net;
  6. //Sense4Net;
  7. {$ELSE}
  8. //S4Single;
  9. Sense4;
  10. {$ENDIF}
  11. const
  12. // 197707074568224603070424
  13. Sense4DevPin = '19770707' + '45682246' + '03070424';
  14. Sense4UserPin = '45682246';
  15. Sense4AuthenPin = '19770707' + '03070424';
  16. Sense4OldDevPin = '12345678' + '12345678' + '12345678';
  17. Sense4OldUserPin = '12345678';
  18. Sense4OldAuthenPin = '12345678' + '12345678';
  19. function OpenSense(var s4Ctx: PSENSE4_CONTEXT): Boolean;
  20. procedure CloseSense(var s4Ctx: PSENSE4_CONTEXT);
  21. function WriteSenseData(s4Ctx: PSENSE4_CONTEXT; AFileID: string; APData: Pointer;
  22. ADataLength: Integer; AIsExe: Boolean; AIsUpdate: Boolean = False): Boolean;
  23. function WriteSenseFile(s4Ctx: PSENSE4_CONTEXT; AFileID: string; AFileName: string;
  24. AIsExe: Boolean; AIsUpdate: Boolean = False): Boolean;
  25. procedure SenseLEDOn(s4Ctx: PSENSE4_CONTEXT);
  26. procedure SenseLEDOff(s4Ctx: PSENSE4_CONTEXT);
  27. procedure SenseLEDFlash(s4Ctx: PSENSE4_CONTEXT);
  28. implementation
  29. uses
  30. Windows, Classes, SysUtils, Variants;
  31. var
  32. g_s4Ctx: PSENSE4_CONTEXT = nil;
  33. tmp_s4Ctx: PSENSE4_CONTEXT = nil;
  34. g_S4Opened: Boolean = False;
  35. // 深思4全局数据(特为网络版设计)
  36. {网络版应该一套软件占用一个授权,即三个应用程序只占用一个授权,
  37. 因此不管启动几个应用程序,都只能使用一次S4Open,
  38. 为此必须采用共享内存来存储深思4的数据,提供跨程序的调用。
  39. }
  40. type
  41. TGlobalS4Data = packed record
  42. // 深思网络锁引用计数
  43. SenseNetDogRefCount: Integer;
  44. // 深思加密锁数据
  45. SenseData: array [0..91] of Byte;
  46. end;
  47. PGlobalS4Data = ^TGlobalS4Data;
  48. const
  49. ScSense4ShareMemoryName = 'SmartCost_Sense4_Data_Handle';
  50. // 返回 0:函数调用失败;1:已存在共享内存对象;2:不存在共享内存对象
  51. function GetGlobalS4Ctx(var s4Ctx: PSENSE4_CONTEXT): Integer;
  52. var
  53. // 文件映射对象句柄
  54. ShareHandle: THandle;
  55. pData: PGlobalS4Data;
  56. SA: TSecurityAttributes;
  57. begin
  58. Result := 0;
  59. SA.nLength := SizeOf(SA);
  60. SA.lpSecurityDescriptor := nil;
  61. SA.bInheritHandle := False;
  62. ShareHandle := CreateFileMapping($FFFFFFFF, @SA, PAGE_READWRITE,
  63. 0, SizeOf(TGlobalS4Data), PChar(ScSense4ShareMemoryName));
  64. try
  65. // 已存在共享内存
  66. if GetLastError = ERROR_ALREADY_EXISTS then
  67. begin
  68. pData := MapViewOfFile(ShareHandle, File_MAP_WRITE, 0, 0, 0);
  69. try
  70. if pData <> nil then
  71. begin
  72. Inc(pData^.SenseNetDogRefCount);
  73. CopyMemory(s4Ctx, @(pData^.SenseData[0]), SizeOf(SENSE4_CONTEXT));
  74. Result := 1;
  75. end;
  76. finally
  77. // if pData <> nil then
  78. // UnmapViewOfFile(pData);
  79. end;
  80. end
  81. // 尚未存在共享内存
  82. else
  83. begin
  84. pData := MapViewOfFile(ShareHandle, File_MAP_WRITE, 0, 0, 0);
  85. try
  86. if pData <> nil then
  87. begin
  88. ZeroMemory(pData, SizeOf(TGlobalS4Data));
  89. pData^.SenseNetDogRefCount := 1;
  90. Result := 2;
  91. end;
  92. finally
  93. // if pData <> nil then
  94. // UnmapViewOfFile(pData);
  95. end;
  96. end;
  97. finally
  98. //CloseHandle(ShareHandle);
  99. end;
  100. end;
  101. function SetGlobalS4Ctx(var s4Ctx: PSENSE4_CONTEXT): Boolean;
  102. var
  103. // 文件映射对象句柄
  104. ShareHandle: THandle;
  105. pData: PGlobalS4Data;
  106. begin
  107. Result := False;
  108. ShareHandle := OpenFileMapping(FILE_MAP_WRITE, False, PChar(ScSense4ShareMemoryName));
  109. if ShareHandle <> Null then
  110. begin
  111. try
  112. pData := MapViewOfFile(ShareHandle, File_MAP_WRITE, 0, 0, 0);
  113. try
  114. if pData <> nil then
  115. begin
  116. CopyMemory(@(pData^.SenseData[0]), s4Ctx, SizeOf(SENSE4_CONTEXT));
  117. Result := True;
  118. end;
  119. finally
  120. if pData <> nil then
  121. UnmapViewOfFile(pData);
  122. end;
  123. finally
  124. CloseHandle(ShareHandle);
  125. end;
  126. end;
  127. end;
  128. function ReleaseGlobalS4Ctx(var s4Ctx: PSENSE4_CONTEXT): Boolean;
  129. var
  130. // 文件映射对象句柄
  131. ShareHandle: THandle;
  132. pData: PGlobalS4Data;
  133. begin
  134. Result := False;
  135. ShareHandle := OpenFileMapping(FILE_MAP_WRITE, False, PChar(ScSense4ShareMemoryName));
  136. if ShareHandle <> Null then
  137. begin
  138. try
  139. pData := MapViewOfFile(ShareHandle, File_MAP_WRITE, 0, 0, 0);
  140. try
  141. if pData <> nil then
  142. begin
  143. Dec(pData^.SenseNetDogRefCount);
  144. if pData^.SenseNetDogRefCount = 0 then
  145. S4Close(s4Ctx);
  146. Result := True;
  147. end;
  148. finally
  149. if pData <> nil then
  150. UnmapViewOfFile(pData);
  151. end;
  152. finally
  153. CloseHandle(ShareHandle);
  154. end;
  155. end;
  156. end;
  157. function OpenSense(var s4Ctx: PSENSE4_CONTEXT): Boolean;
  158. var
  159. CtxLength: Cardinal;
  160. begin
  161. Result := False;
  162. CtxLength := 0;
  163. {$IFDEF _ScNET}
  164. { 网络版为了控制节点数,必须保持OPEN状态,
  165. 而原来单机版的做法是OPEN后检查完就CLOSE;
  166. 好在OpenSense, CloseSense是成对调用,所以可做如下修改:
  167. 为兼容单机版的做法,在这里不每次打开,只是第一次打开,
  168. 另创建一个指针,并将传入的指针保存,
  169. 再把创建的指针传出去
  170. 在CloseSense时,不关闭,只把指针替换为原来传进来的指针}
  171. if g_s4Ctx = nil then
  172. begin
  173. S4Enum(nil, CtxLength);
  174. if CtxLength = 0 then Exit;
  175. New(g_s4Ctx);
  176. try
  177. if S4Enum(g_s4Ctx, CtxLength) = S4_SUCCESS then
  178. begin
  179. if S4Open(g_s4Ctx) = S4_SUCCESS then
  180. begin
  181. g_S4Opened := True;
  182. Result := True;
  183. end;
  184. end;
  185. { case GetGlobalS4Ctx(g_s4Ctx) of
  186. // 失败
  187. 0:
  188. Exit;
  189. // 已有其他版本程序打开锁
  190. 1:
  191. begin
  192. g_S4Opened := True;
  193. Result := True;
  194. end;
  195. // 首次打开锁
  196. 2:
  197. begin
  198. if S4Enum(g_s4Ctx, CtxLength) = S4_SUCCESS then
  199. begin
  200. if S4Open(g_s4Ctx) = S4_SUCCESS then
  201. begin
  202. g_S4Opened := True;
  203. SetGlobalS4Ctx(g_s4Ctx);
  204. Result := True;
  205. end;
  206. end;
  207. end;
  208. end;}
  209. except
  210. Result := False;
  211. end;
  212. end
  213. else
  214. Result := True;
  215. tmp_s4Ctx := s4Ctx;
  216. s4Ctx := g_s4Ctx;
  217. {$ELSE}
  218. S4Enum(nil, CtxLength);
  219. if CtxLength = 0 then Exit;
  220. try
  221. if S4Enum(s4Ctx, CtxLength) = S4_SUCCESS then
  222. begin
  223. if S4Open(s4Ctx) = S4_SUCCESS then
  224. begin
  225. Result := True;
  226. end;
  227. end;
  228. except
  229. Result := False;
  230. end;
  231. {$ENDIF}
  232. end;
  233. procedure CloseSense(var s4Ctx: PSENSE4_CONTEXT);
  234. begin
  235. {$IFDEF _ScNet}
  236. { 网络版为了控制节点数,必须保持OPEN状态,
  237. 而原来单机版的做法是OPEN后检查完就CLOSE;
  238. 为兼容单机版的做法,在这里不关闭,只是将OPEN时传入的指针再传出去
  239. 在程序关闭时再CLOSE}
  240. if Assigned(tmp_s4Ctx) then
  241. begin
  242. s4Ctx := tmp_s4Ctx;
  243. tmp_s4Ctx := nil;
  244. end
  245. else if s4Ctx = g_s4Ctx then
  246. begin
  247. s4Ctx := nil;
  248. New(s4Ctx);
  249. end;
  250. {$ELSE}
  251. S4Close(s4Ctx);
  252. {$ENDIF}
  253. end;
  254. function WriteSenseData(s4Ctx: PSENSE4_CONTEXT; AFileID: string; APData: Pointer;
  255. ADataLength: Integer; AIsExe: Boolean; AIsUpdate: Boolean): Boolean;
  256. var
  257. iBytes: Cardinal;
  258. iFileType: Byte;
  259. iFlag: Cardinal;
  260. iResult: Cardinal;
  261. begin
  262. {$IFDEF _ScNet}
  263. Result := True;
  264. {$ELSE}
  265. Result := False;
  266. if AIsExe then
  267. iFileType := S4_EXE_FILE
  268. else
  269. iFileType := S4_DATA_FILE;
  270. if AIsUpdate then
  271. iFlag := S4_UPDATE_FILE
  272. else
  273. iFlag := S4_CREATE_NEW;
  274. if S4VerifyPin(s4Ctx, Sense4DevPin, 24, S4_DEV_PIN) = S4_SUCCESS then
  275. begin
  276. iResult := S4WriteFile(s4Ctx, PChar(AFileID), 0, APData, ADataLength,
  277. ADataLength, iBytes, iFlag, iFileType);
  278. Result := iResult = S4_SUCCESS;
  279. end;
  280. {$ENDIF}
  281. end;
  282. function WriteSenseFile(s4Ctx: PSENSE4_CONTEXT; AFileID: string; AFileName: string;
  283. AIsExe: Boolean; AIsUpdate: Boolean): Boolean;
  284. var
  285. fsFile: TFileStream;
  286. pData: Pointer;
  287. begin
  288. fsFile := TFileStream.Create(AFileName, fmOpenRead);
  289. try
  290. pData := AllocMem(fsFile.Size);
  291. try
  292. ZeroMemory(pData, fsFile.Size);
  293. fsFile.Seek(0, soFromBeginning);
  294. fsFile.Read(pData^, fsFile.Size);
  295. Result := WriteSenseData(s4Ctx, AFileID, pData, fsFile.Size, AIsExe, AIsUpdate);
  296. finally
  297. FreeMem(pData);
  298. end;
  299. finally
  300. fsFile.Free;
  301. end;
  302. end;
  303. procedure SenseLEDOn(s4Ctx: PSENSE4_CONTEXT);
  304. var
  305. iReturn: Cardinal;
  306. begin
  307. {$IFNDEF _ScNet}
  308. S4Control(s4Ctx, S4_LED_UP, nil, 0, nil, 0, iReturn);
  309. {$ENDIF}
  310. end;
  311. procedure SenseLEDOff(s4Ctx: PSENSE4_CONTEXT);
  312. var
  313. iReturn: Cardinal;
  314. begin
  315. {$IFNDEF _ScNet}
  316. S4Control(s4Ctx, S4_LED_DOWN, nil, 0, nil, 0, iReturn);
  317. {$ENDIF}
  318. end;
  319. procedure SenseLEDFlash(s4Ctx: PSENSE4_CONTEXT);
  320. var
  321. iReturn: Cardinal;
  322. begin
  323. {$IFNDEF _ScNet}
  324. S4Control(s4Ctx, S4_LED_WINK, nil, 0, nil, 0, iReturn);
  325. {$ENDIF}
  326. end;
  327. initialization
  328. finalization
  329. if g_S4Opened and (g_s4Ctx <> nil) then
  330. //ReleaseGlobalS4Ctx(g_s4Ctx);
  331. S4Close(g_s4Ctx);
  332. end.