Create a GUID, a Globally Unique Identifier

From NSIS Wiki
Jump to navigationJump to search
Author: anonymous (talk, contrib)


Description

Supports: Win9x, WINNT, WIN2K and WINXP.
Requires: System plug-in.

Creates a GUID, or Globally Unique Identifier. Thanks to everyone who helped with the hex and character array issues.

The Function

;Call CreateGUID
;Pop $0 ;contains GUID
Function CreateGUID
  System::Call 'ole32::CoCreateGuid(g .s)'
FunctionEnd

Helper Macro (optional)

;${CreateGUID} $0 ; $0 contains GUID
 
;${CreateGUID} s
;Pop $0 ;contains GUID
 
!define CreateGUID `!insertmacro _CreateGUID`
!macro _CreateGUID _RetVar
    Call CreateGUID
    !if ${_RetVar} != s
        Pop ${_RetVar}
    !endif
!macroend

Superseded Versions

Brainsucker's Version

Update: bugfixed on 30 Nov 2004 by StB.

;Call CreateGUID
;Pop $0 ;contains GUID
Function CreateGUID
  Push $0
  Push $1
  Push $2
  System::Alloc 80 
  System::Alloc 16 
  System::Call 'ole32::CoCreateGuid(i sr1) i' 
  System::Call 'ole32::StringFromGUID2(i r1, i sr2, i 80) i' 
  System::Call 'kernel32::WideCharToMultiByte(i 0, i 0, i r2, \
                i 80, t .r0, i ${NSIS_MAX_STRLEN}, i 0, i 0) i' 
  System::Free $1 
  System::Free $2
  Pop $2
  Pop $1
  Exch $0
FunctionEnd

Original Version

Update: bugfixed on 30 Nov 2004 by StB.

;Call CreateGUID
;Pop $0 ;contains GUID
Function CreateGUID
  ; GUID has 128 bit = 16 byte = 32 hex characters
  Push $R0
  Push $R1
  Push $R2
  Push $R3
  Push $R4
  ;allocate space for character array
  System::Alloc 16
  ;get pointer to new space
  Pop $R1
  StrCpy $R0 "" ; init
  ;call the CoCreateGuid api in the ole32.dll
  System::Call 'ole32::CoCreateGuid(i R1) i .R2'
  ;if 0 then continue
  IntCmp $R2 0 continue 
  ; set error flag
  SetErrors
  goto done
continue:
  ;byte counter = 0
  StrCpy $R3 0
loop:
    System::Call "*$R1(&v$R3, &i1 .R2)"
    ;now $R2 is byte at offset $R3
    ;convert to hex
    IntFmt $R4 "%X" $R2
    StrCpy $R4 "00$R4"
    StrLen $R2 $R4
    IntOp $R2 $R2 - 2
    StrCpy $R4 $R4 2 $R2
    ;append to result
    StrCpy $R0 "$R0$R4"
    ;increment byte counter
    IntOp $R3 $R3 + 1
    ;if less than 16 then continue
    IntCmp $R3 16 0 loop
done:
  ;cleanup
  System::Free $R1
  ; BEGIN format GUID
  StrCpy $R1 "$R0"
  StrCpy $R0 "{"
  StrCpy $R2 $R1 8
  StrCpy $R0 "$R0$R2-"
  StrCpy $R2 $R1 4 8
  StrCpy $R0 "$R0$R2-"
  StrCpy $R2 $R1 4 12
  StrCpy $R0 "$R0$R2-"
  StrCpy $R2 $R1 4 16
  StrCpy $R0 "$R0$R2-"
  StrCpy $R2 $R1 12 20
  StrCpy $R0 "$R0$R2}"
  ; END format GUID
  Pop $R4
  Pop $R3
  Pop $R2
  Pop $R1
  Exch $R0
FunctionEnd