
#DefineFunction SignCallbackProc(Sign_Handle,Sign_Message,Sign_ID,Sign_EventInfo,rsvd)
   switch Sign_Message                                     ; Switch based on Dialog Message type
      case @deInit                                         ; Standard Initialization message
         DialogProcOptions(Sign_Handle,@dePbPush,@TRUE)

			;Define ini file 
			ptr_ini = PtrGlobal( ini )

			;Read Ini File Settings
			filetosign = IniReadPvt( 'Settings', 'filetosign', '', *ptr_ini )
			friendlyname = IniReadPvt( 'Settings', 'friendlyname', '', *ptr_ini )
			desc = IniReadPvt( 'Settings', 'desc', '', *ptr_ini )
			url = IniReadPvt( 'Settings', 'url', '', *ptr_ini )
			timestamp = IniReadPvt( 'Settings', 'timestamp', '', *ptr_ini )
			;Initialize Edit box controls with data from ini
			if filetosign != '' then DialogControlSet( Sign_Handle, "edFileToSign", @dcText, filetosign )
			if friendlyname != '' then DialogControlSet( Sign_Handle, "edFriendlyName", @dcText, friendlyname )
			if desc != '' then DialogControlSet( Sign_Handle, "edDescription", @dcText, desc )
			if url != '' then DialogControlSet( Sign_Handle, "edUrl", @dcText, url )
			if timestamp != '' then DialogControlSet( Sign_Handle, "edTimeStamp", @dcText, timestamp )
         if StrReplace(Winversion(5),'-','') < '262'
            rfc3121 = 0
            DialogControlState(Sign_Handle,"cbRfc3161",@dcsAddStyle,@csDisabled )  ; RFC316 Timestamp not supported until Win 8/2012
         else
			   rfc3121 = IniReadPvt( 'Settings', 'rfc3161', '', *ptr_ini )
            if !IsInt(rfc3121) then  rfc3121 = 0
         endif
         DialogControlSet(Sign_Handle,"cbRfc3161", @dcCheck, rfc3121 )

         return(@retDefault)

     case @dePbPush
        switch  1
           case "PushButton_1" == Sign_ID                   ; Sign EXE

			     filetosign = DialogControlGet( Sign_Handle, "edFileToSign", @dcText )  ;get all text in editbox.
              ;Check if file name specified
              If !FileExist(filetosign) 
                  Message("Notice!","Please specify a valid file name.")
                  return(@retNoExit)
              Endif
              
              ;Check if friendlyname specified
              friendlyname = DialogControlGet( Sign_Handle, "edFriendlyName", @dcText )  ;get all text in editbox.
              If friendlyname == "" || StrLen(friendlyname)<4
                  Message("Notice!","Please specify a valid friendlyname. Should be at least 4 characters or more.")
                  return(@retNoExit)
              Endif

              ;Read in Description of certificate if any
              desc = DialogControlGet( Sign_Handle, "edDescription", @dcText )  ;get all text in editbox.

              ;Read in URL of certificate if any
              url = DialogControlGet( Sign_Handle,"edUrl", @dcText )  ;get all text in editbox.

				  ;Read in Timestamp of certificate if any
              timestamp = DialogControlGet( Sign_Handle, "edTimeStamp", @dcText )  ;get all text in editbox.

              ; RFC 316
              p1 = 0
              if StrReplace(Winversion(5),'-','') >= '262'  ; Win 8/2012 or newer required
                 rfc3161 = DialogControlGet( Sign_Handle,"cbRfc3161", @dcCheck) 
                 if rfc3161 then p1 = 3
              endif
  
	            ; Performs Code Signing.
	            ;
	            ;    p1   Meaning
	            ;    --   -------
	            ;     0   Sign a file (Windows XP and newer)
	            ;           p2 specifies a tab-delimited string with the following parameters:
	            ;             file to sign
	            ;             certificate friendly name
	            ;             description of file being signed (or blank string)
	            ;             location (URL) of information about file (or blank string)
	            ;             URL of timestamp server !Important! (or blank string)
	            ;
        			;		3   Sign a file and use an RFC-3161-compliant Timestamp Server (Windows 8 or newer.)
               ;           p2 specifies a tab-delimited string with the following six parameters:
               ;             file to sign
               ;             certificate friendly name
               ;             description of file being signed (can be "" if not needed)
               ;             location (URL) of information about file (can be "" if not needed)
               ;             URL of RFC-3161-compliant timestamp server (can be "" if not needed)
               ;             timestamp server's hash algorithm: sha1, sha256, sha385, or sha512 (defaults 
               ;               to sha256 if "" and ignored if no timestamp server provided)

              ; Sign file based on certificate data like friendly name 
              certdata =  filetosign : @tab : friendlyname : @tab : desc : @tab : url : @tab : timestamp
              if p1 == 3 then  certdata := @tab : "SHA256"
              IntControl(93, p1, certdata, 0,  0)
              Message("Notice!", "The file has been signed successfully.")

				  ;Update ini file with new settings
				  ;Define ini file 
				  ptr_ini = PtrGlobal( ini )
				  IniWritePvt( 'Settings', 'filetosign', filetosign, *ptr_ini )
				  IniWritePvt( 'Settings', 'friendlyname', friendlyname, *ptr_ini )
				  IniWritePvt( 'Settings', 'desc', desc, *ptr_ini )
				  IniWritePvt( 'Settings', 'url', url, *ptr_ini )
				  IniWritePvt( 'Settings', 'timestamp', timestamp, *ptr_ini )
              if StrReplace(Winversion(5),'-','') >= '262'  ; Win 8/2012 or newer required
			        IniWritePvt( 'Settings', 'rfc3161', rfc3161, *ptr_ini )
				  endif
				  
              return(@retDefault)

           case "PushButton_Cancel" == Sign_ID              ; Cancel
              return(@retDefault)

           case "PushButton_Browse" == Sign_ID              ; Browse...
              dafile = AskFileName( "Choose files to sign", "C:\", "Executable|*.exe|All Files|*.*", "", 2 )              
              DialogControlSet( Sign_Handle, "edFileToSign", @dcText, dafile )
              return(@retNoExit)

        endswitch                                           ; Sign_ID
        return(@retDefault)

   endswitch                                                ; Sign_Message
   return(@retDefault)
   :Cancel
   Exit
#EndFunction                                                ; End of Dialog Callback SignCallbackProc



;***************************************************************************
;** 
;**       Sign Code
;** 
;** 
;** Purpose: This code can be used to code sign an EXE.
;** Inputs:  SPC file, PVK File, Private key password, Friendly name for certificate.
;** Outputs: NONE
;** Revisions: 1001
;**            1002 - IntControl 93's p1 == 3 support added.
;***************************************************************************


; Check if running 2017B or newer
ver = VersionDLL( )
If ver < "2017B"
   Message("Sorry", "WIL version 2017B or newer required")
   Exit
EndIf

;Define Ini File
ini = ShortCutDir('AppData') : '\WinBatch\Settings\signcode.ini'
PtrGlobalDefine( ini )

timestamp = 'http://timestamp.verisign.com/scripts/timstamp.dll'

SignFormat=`WWWDLGED,6.2`

SignCaption=`Sign Code`
SignX=240
SignY=237
SignWidth=302
SignHeight=174
SignNumControls=015
SignProcedure=`SignCallbackProc`
SignFont=`DEFAULT`
SignTextColor=`DEFAULT`
SignBackground=`DEFAULT,DEFAULT`
SignConfig=0

Sign001=`105,153,030,011,PUSHBUTTON,"PushButton_1",DEFAULT,"Sign EXE",1,8,@csDefButton,DEFAULT,DEFAULT,DEFAULT`
Sign002=`148,153,033,011,PUSHBUTTON,"PushButton_Cancel",DEFAULT,"Cancel",0,9,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign003=`018,015,261,024,STATICTEXT,"StaticText_1",DEFAULT,"You have successfully installed your private key and certificate. If you would like to test sign a file please choose the file you would like to sign.",DEFAULT,9,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign004=`022,046,049,009,STATICTEXT,"StaticText_2",DEFAULT,"File to sign:",DEFAULT,10,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign005=`244,044,030,011,PUSHBUTTON,"PushButton_Browse",DEFAULT,"Browse...",2,2,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign006=`079,044,158,011,EDITBOX,"edFileToSign",filetosign,DEFAULT,DEFAULT,1,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign007=`022,063,049,008,STATICTEXT,"StaticText_3",DEFAULT,"Friendly name",DEFAULT,12,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign008=`079,079,158,011,EDITBOX,"edDescription",desc,DEFAULT,DEFAULT,4,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign009=`022,081,049,006,STATICTEXT,"StaticText_Description",DEFAULT,"Description",DEFAULT,13,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign010=`079,097,158,011,EDITBOX,"edUrl",url,DEFAULT,DEFAULT,5,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign011=`022,116,049,009,STATICTEXT,"StaticText_5",DEFAULT,"Timestamp server",DEFAULT,15,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign012=`079,114,158,011,EDITBOX,"edTimeStamp",timestamp,DEFAULT,DEFAULT,6,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign013=`079,062,158,009,EDITBOX,"edFriendlyName",friendlyname,DEFAULT,DEFAULT,3,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign014=`022,098,049,010,STATICTEXT,"StaticText_Website",DEFAULT,"Website",DEFAULT,14,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
Sign015=`079,134,104,009,CHECKBOX,"cbRfc3161",rfc3161,"RFC 3161 (SHA256) Timestamp",1,7,DEFAULT,DEFAULT,DEFAULT,DEFAULT`

ButtonPushed=Dialog("Sign")



:Cancel
Exit








