2022年4月26日 星期二

如何使用 Win32 API 存取 RS232

 http://www.finetech.idv.tw/techdoc/bcbrs232/bcbrs232.htm

 https://stackoverflow.com/questions/820817/low-level-control-of-rs232-com-port-rts-cts-dtr-dsr-possible

Win32 API Communication Functions  

BOOL SetCommState(
    HANDLE hFile,    // handle of communications device
    LPDCB lpDCB            // address of device-control block structure
   );

 
    Windows App Win32 API System Services Winbase.h

SetCommState function (winbase.h)

 
http://delphi-kb.blogspot.com/2009/03/how-to-communicate-with-com-port.html
https://docs.microsoft.com/zh-tw/windows/win32/api/winbase/nf-winbase-setcommstate 


unit ComPort;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TComPort = class(TObject)
  private
    ComID, ComError: Integer;
    DcbOld: TDCB;
    CommTimeoutsOld: TCommTimeouts;
  protected
  public
    function Open(PortNo: integer): boolean;
    procedure Close;
    function Config(Baudrate: DWORD; ByteSize, StopBits, Parity: Byte): boolean;
    function ReadBlock(var Ch: array of char; BlockSize: dword): integer;
    function ReadChar(var Ch: char): boolean;
    function WriteBlock(var Ch: array of char; BlockSize: dword): boolean;
    function WriteChar(Ch: char): boolean;
    procedure Purge;
    function Error: integer;
    constructor Create;
  published
  end;



https://docs.microsoft.com/en-us/previous-versions/ms810467(v=msdn.10)?redirectedfrom=MSDN

Serial Communications in Win32
multiple threading and synchronization in Win32. In addition, a basic understanding of the Win32 heap functions is useful to fully comprehend the memory management methods used by the Multithreaded TTY (MTTTY) 

spcomm mscomm Tcomm Cport CnRS232 MScom SPCOM

Delphi串口通信技术与工程实践

 

https://github.com/MHumm/ComPortDriver

https://github.com/CWBudde/ComPort-Library

https://github.com/joelsernamoreno/WSD/blob/master/tools/nodemcu-flasher-master/SPComm.pas

https://torry.net/pages.php?id=198

http://www.tetraedre.com/advanced/serial/msdn_serial.htm

powershell "$port= new-Object System.IO.Ports.SerialPort

https://theitbros.com/how-to-delete-com-ports-in-use/

Docs Windows Server Windows 命令 參考
mode
顯示 [系統狀態]、[變更系統設定] 或 [重新設定埠] 或 [裝置]。 如果使用時不含參數,則 模式 會顯示主控台和可用 COM 裝置的所有可控制屬性。

https://docs.microsoft.com/zh-tw/windows-server/administration/windows-commands/mode

DLL "LoadLibrary " +"delphi" import dll Libraries and Packages Delphi

 "LoadLibrary "  +"delphi"   import dll Libraries and Packages Delphi

 Dr.Bob's Delphi Clinic: Using C DLLs with Delphi (and HeadConv v4.20)

 https://www.drbob42.com/Delphi/headconv.htm

 http://www.drbob42.com/tools/drbob.htm

 Dr.Bob's SwarTools: Dr.Bob's Collection of Delphi Experts/Wizards v2.50

 https://infosys.beckhoff.com/english.php?content=../content/1033/tcsample_bdelphi/html/TcAdsOcx_Setup_Delphi.htm&id=

 https://www.mql5.com/en/articles/96

https://blogs.embarcadero.com/how-to-use-a-c-dll-in-any-delphi-program/

 http://etutorials.org/Programming/mastering+delphi+7/Part+II+Delphi+Object-Oriented+Architectures/Chapter+10+Libraries+and+Packages/Creating+a+DLL+in+Delphi/

 https://github.com/PacktPublishing/Delphi-High-Performance/tree/master/Chapter%208

 http://etutorials.org/Programming/mastering+delphi+7/Part+II+Delphi+Object-Oriented+Architectures/Chapter+10+Libraries+and+Packages/Using+Existing+DLLs/

http://theprofessionalspoint.blogspot.com/2014/01/calling-conventions-in-delphi-safecall.html

 https://docwiki.embarcadero.com/RADStudio/Sydney/en/Program_Control_(Delphi)

Delphi DLL function stdcall external

COM Component Object Model  

COM+ 

DCOM Distributed Component Object Model

 https://stackoverflow.com/questions/17937225/delphi-how-to-import-type-library-for-new-itextrange2-type-interfaces

 tlibimp Embarcadero Type Library Exporter

 RegAsm

https://blogs.embarcadero.com/using-a-net-assembly-via-com-in-delphi/ 

 DLL external COM Component Object Model  interface

https://docwiki.embarcadero.com/RADStudio/Sydney/en/Overview_of_COM_Technologies

Using Visual C++ DLLs in a C++Builder Project

https://blogs.embarcadero.com/use-the-dll-created-by-visual-c-2017-with-c-builder-win64/

https://www.marshallsoft.com/wsc_4c.pdf

Windows Standard Serial Communications for C/C++ ...

https://github.com/sefcom/honeyplc/blob/master/snap7/doc/Snap7-refman.pdf

https://github.com/sefcom/honeyplc

https://sourceforge.net/projects/libusb-win32/

embarcadero import tools  DLL external COM Component Object Model Importing Type Library Information

https://www.c-sharpcorner.com/UploadFile/nipuntomar/describing-com-component-object-model/

Component Object Model Importing Type Library Information guid interface

 CoCreateInstance IDispatch IUnknow

The following is a list of tips and tricks that might be useful to COM developers of all levels. If you have an interesting tip that's not listed here, please submit it to me and I'll add it to the list if I think it's useful.

http://www.techvanguards.com/com/tutorials/tips.asp

https://www.codeproject.com/Questions/373094/In-the-c-plus-plus-to-Delphi

GPIB-488

 This is one-purpose program created for management of experiment on custom  aparatus. His goal take measurements of values for computation if Seebeck  coefficient

 https://github.com/pinkavaj/seebrez/blob/master/GPIB-488/Language%20Interfaces/Delphi/GPIB.PAS

 seebrez/GPIB-488/Language Interfaces/Delphi/

 https://www.ni.com/zh-tw/support/downloads/drivers/download.ni-488-2.html#442610

  NI-488.2 with LabVIEW

 

 

 

 

 

 

 

 

https://github.com/pinkavaj/seebrez/tree/master/TPCM.

Base64 Image System.NetEncoding.TBase64Encoding

https://github.com/emn178/hi-base64

 https://github.com/whatwg/wattsi/blob/main/src/lib/base64encoder.pas

 https://docwiki.embarcadero.com/Libraries/Sydney/en/System.NetEncoding.TBase64Encoding

unction BaseImage(fn: string): string;
var
    m1: TMemoryStream;
    m2: TStringStream;
    str: string;
begin
    m1 := TMemoryStream.Create;
    m2 := TStringStream.Create('');
    m1.LoadFromFile(fn);
    EncdDecd.EncodeStream(m1, m2);                       
    str := m2.DataString;
    str := StringReplace(str, #13, '', [rfReplaceAll]); 
    str := StringReplace(str, #10, '', [rfReplaceAll]);
    result := str;                                      
    m1.Free;
    m2.Free;
end;

 https://flixengineering.com/archives/270

 http://www.delphimagazine.com/2019/05/21/5-minute-snack-base64-encode-and-decode-images-in-delphi/

  1. procedure TFrmMain.btnLoadImageClick(Sender: TObject);
  2. var
  3. LInput : TMemoryStream;
  4. LOutput: TMemoryStream;
  5. begin
  6. // show open file dialog
  7. if
  8. dlgOpen.Execute then
  9. begin
  10. // load image into image component (TPicture)

  11. Image.Picture.LoadFromFile(dlgOpen.FileName);
  12. LInput := TMemoryStream.Create;
  13. LOutput := TMemoryStream.Create;

  14. // write picture to stream and encode
  15. try
  16. Image.Picture.SaveToStream(LInput);
  17. LInput.Position := 0;
  18. TNetEncoding.Base64.Encode( LInput, LOutput );
  19. LOutput.Position := 0;
  20. Memo.Lines.LoadFromStream( LOutput );
  21. finally
  22. LInput.Free;
  23. LOutput.Free;
  24. end;
  25. end;
  26. end;
  27.  

 

  1. procedure TFrmMain.btnLoadTextClick(Sender: TObject);
  2. var
  3. LInput: TMemoryStream;
  4. LOutput: TMemoryStream;
  5. begin
  6. if dlgOpen.Execute then
  7. begin
  8. Memo.Lines.LoadFromFile(dlgOpen.FileName);
  9. LInput := TMemoryStream.Create;
  10. LOutput := TMemoryStream.Create;

  11. try
  12. Memo.Lines.SaveToStream(LInput);
  13. LInput.Position := 0;
  14. TNetEncoding.Base64.Decode( LInput, LOutput );
  15. LOutput.Position := 0;
  16. Image.Picture.LoadFromStream(LOutput);
  17. finally
  18. LInput.Free;
  19. LOutput.Free;
  20. end;
  21. end;
  22. end;

unit uPublicSHA256WithRsa;

interface

uses Winapi.Windows,System.Classes, System.SysUtils,libeay32,ComObj;


const
  BIO_FLAGS_BASE64_NO_NL = $100;

type
  TSHA1Buffer = array [1..20] of byte;
  TSHA256Buffer= array[1..32] of Byte;
  TRSA_Buf_1024 = array[1..128] of byte; //1024bit RSA 樓躇怀堤
  TRSA_Buf_2048 = array[1..256] of byte; //2048bit RSA 樓躇怀堤

  TAES_Key_128 = array[1..16] of byte;

  TMD5_Digest = array[1..16] of byte;//md5 靡賦彆

  THA256_Digest = array[1..16] of byte; //SHA256 靡賦彆


  PsfAES_CBC_Data=^TsfAES_CBC_Data;
  TsfAES_CBC_Data = record
    InBuf:Pointer;
    InLen:Integer;
    Key:TAES_Key_128;
    ivec:TAES_Key_128;
  end;

  psfRSA = ^libeay32.RSA;

  TSHA256WithRSAOpenSSL=class
  protected
    FstrPublicKey:AnsiString;
    FstrPrivateKey:AnsiString;
  protected
   
    function base64_decode(Data:PAnsiChar;DataLen:Cardinal;bSingleRow:Boolean=FALSE):AnsiString;
 
    function base64_encode(Data:Pointer;Len:Integer;bSingleRow:Boolean=FALSE):AnsiString;

    function LoadPublicKey(PUBLIC_Key:AnsiString):pEVP_PKEY;
    function LoadPrivateKey(PRIVATE_Key:AnsiString):pEVP_PKEY;
  public
    function SHA256WithRSASign(const TextBuf:PAnsiChar;BufLen:Integer):AnsiString;
    function SHA256WithRSASign_verify(Data:PAnsichar;RsaSign:PAnsichar):Boolean;

    constructor Create(PUBLIC_Key,PRIVATE_Key:AnsiString);
    destructor Destroy; override;
  end;


implementation

uses
  uLogThread;

{ TSHA256WithRSAOpenSSL }

function TSHA256WithRSAOpenSSL.base64_decode(Data: PAnsiChar; DataLen: Cardinal;
  bSingleRow: Boolean): AnsiString;
var
  BIO,b64:PBIO;
  L:Integer;
begin
  b64 := Libeay32.BIO_new(BIO_f_base64());
  if bSingleRow then
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  bio := Libeay32.BIO_new_mem_buf(Data,DataLen);
  bio := Libeay32.BIO_push(b64, bio);
  SetLength(Result,DataLen);
  L := Libeay32.BIO_read(bio,PAnsichar(Result),Length(Result));
  SetLength(Result,L);
  Libeay32.BIO_free_all(bio);

end;

function TSHA256WithRSAOpenSSL.base64_encode(Data: Pointer; Len: Integer;
  bSingleRow: Boolean): AnsiString;
var
  bio,b64:libeay32.pBIO;
  bptr: libeay32.PBUF_MEM ;
  pbptr:libeay32.PPBUF_MEM;
  I:Integer;
begin
  b64 := libeay32.BIO_new(BIO_f_base64());
  TRY
    if bSingleRow then
    begin
      libeay32.BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    end;

    bio := libeay32.BIO_new(BIO_s_mem());

    b64 := BIO_push(b64, bio);

    I := libeay32.BIO_write(b64, Data, Len);
    if I < 0 then
      Exit;
    I := libeay32.BIO_flush(b64);

    pbptr := @bptr;
    I := libeay32.BIO_get_mem_ptr(b64, pbptr); //頗蔚BIO_C_GET_BUF_MEM_PTR紱釬換菰跤bio
    if I < 0 then
    begin
      Result := '';
      Exit;
    end;

    SetLength(Result,bPtr^.length);
    Move(bPtr^.data^,Result[1],bPtr^.length);
  FINALLY
    libeay32.BIO_Free_All(b64); //坻頗庋溫淕跺蟈沭
  END;

end;

constructor TSHA256WithRSAOpenSSL.Create(PUBLIC_Key, PRIVATE_Key: AnsiString);
begin
  try
    OpenSSL_add_all_algorithms;
    OpenSSL_add_all_ciphers;
    OpenSSL_add_all_digests;
    ERR_load_crypto_strings;
    ERR_load_RSA_strings;

    FstrPublicKey :=PUBLIC_Key;
    FstrPrivateKey :=PRIVATE_Key;

    if FstrPublicKey='' then
      raise Exception.Create('PublicKey Invalid');

    if FstrPrivateKey='' then
      raise Exception.Create('Privatekey Invalid');
  except
    on e:Exception do
    begin
      aiLog.Info(Format('[TSHA256WithRSAOpenSSL.Create][message=%s]',[e.Message]));
      raise e;
    end;
  end;
end;

destructor TSHA256WithRSAOpenSSL.Destroy;
begin
  try
    EVP_cleanup;
    ERR_free_strings;
    inherited;
  except
    on e:Exception do
    begin
      aiLog.Info(Format('[TSHA256WithRSAOpenSSL.Destroy]',[e.Message]));
      raise e;
    end;
  end;
end;


function TSHA256WithRSAOpenSSL.LoadPrivateKey(
  PRIVATE_Key: AnsiString): pEVP_PKEY;
var
  keyBO : PBIO;
  aRsa:pEVP_PKEY;
  iRet:integer;
begin
  aRsa :=nil;
  keyBO :=nil;

  keyBO := BIO_new_mem_buf(PAnsiChar(PRIVATE_Key),Length(PAnsiChar(PRIVATE_Key)));
  try
    Result := PEM_read_bio_PrivateKey(keyBO,aRsa,nil,nil);
  finally
    BIO_free_all(keyBO);
  end;
end;

function TSHA256WithRSAOpenSSL.LoadPublicKey(PUBLIC_Key: AnsiString): pEVP_PKEY;
var
  keyBO: PBIO;
  aRsa:pEVP_PKEY;
begin

  aRsa :=nil;
  keyBO :=nil;

  keyBO := BIO_new_mem_buf(PAnsiChar(PUBLIC_Key),Length(PAnsiChar(PUBLIC_Key)));
  try
    Result :=PEM_read_bio_PUBKEY(keyBO,aRsa,nil,nil)
  finally
    BIO_free_all(keyBO);
  end;
end;

function TSHA256WithRSAOpenSSL.SHA256WithRSASign(const TextBuf: PAnsiChar;
  BufLen: Integer): AnsiString;
var
  outSHA256: TSHA256Buffer;
  RSA_SignBinValue: TRSA_Buf_2048;
  CTX:EVP_MD_CTX;
  mLen:cardinal;
  SigLen,iRet:Integer;
  priKey:pEVP_PKEY;
begin
  ZeroMemory(@outSHA256,Length(outSHA256));
  ZeroMemory(@RSA_SignBinValue,Length(RSA_SignBinValue));

  priKey :=LoadPrivateKey(FstrPrivateKey);

  if priKey=nil then exit;

  EVP_MD_CTX_init(@CTX);
  try
    EVP_SignInit(@CTX,EVP_sha256());
    EVP_SignUpdate(@CTX,TextBuf,BufLen);
    EVP_DigestFinal(@CTX,@outSHA256,mLen);
    iRet := libeay32.RSA_sign(EVP_sha256()._type,
                                @outSHA256,
                                mLen,
                                @RSA_SignBinValue,
                                @SigLen,
                                priKey.pkey.rsa);

    if iRet > 0 then
      Result := base64_encode(@RSA_SignBinValue,SizeOf(RSA_SignBinValue),TRUE);
  finally
    EVP_PKEY_free(priKey);
    EVP_MD_CTX_cleanup(@CTX);
  end;
end;

function TSHA256WithRSAOpenSSL.SHA256WithRSASign_verify(Data,
  RsaSign: PAnsichar): Boolean;
var
  Sha256Buf:TSHA256Buffer;
  ctx: EVP_MD_CTX;
  RsaBuf: AnsiString;
  mlen: DWORD;
  iRet: Integer;
  pEVPKey:pEVP_PKEY;
begin
  Result :=false;
  pEVPKey :=LoadPublicKey(FstrPublicKey);

  if pEVPKey=nil then Exit;

  RSA_memory_lock(pEVPKey.pkey.rsa);
  libeay32.EVP_MD_CTX_init(@ctx);
  try
    EVP_SignInit(@ctx,EVP_sha256());
    EVP_SignUpdate(@ctx,Data,StrLen(Data));
    EVP_DigestFinal(@ctx,@Sha256Buf,mlen);
    RsaBuf := base64_decode(RsaSign,StrLen(RsaSign),TRUE);
    iRet := RSA_verify(EVP_sha256()._type,@Sha256Buf,SizeOf(Sha256Buf),PAnsichar(RsaBuf),Length(RsaBuf),pEVPKey.pkey.rsa);
    Result := (iRet = 1);
  finally
    EVP_PKEY_free(pEVPKey);
    libeay32.EVP_MD_CTX_cleanup(@ctx);
  end;
end;

end.