The script is in a rough state -- meaning I haven't polished the display
and my use of the environment. It probably won't get much better unless
there is unexpected interest. It was written on Windows Vista but if it
fails on Windows XP or Windows 7 it can probably be fixed. It uses
"%SystemRoot%\System32\getmac.exe". If that isn't available (not on
system or not permitted access) I can fix it.
In the top of the script there are a few sample UUIDs if you just want
to see how they are constructed.
Frank
::Version 1 A time-based UID.
:: 2b422150-d42b-11de-8a39-0800200c9a66
:: 2fac1234-31f8-11b4-a222-08002b34c003
::Version 3 A name-based UID which uses MD5 hashing.
:: A2E3D453-6AF6-304A-94F5-017024598F63
:: e902893a-9d22-3c7e-a7b8-d6e313b71d9f
::Version 4 A randomly or pseudo-randomly generated UID.
:: f47ac10b-58cc-4372-a567-0e02b2c3d479.
:: 127FB026-B05D-4783-A810-B7A69DA6C96C
:: a32a3277-578c-4da1-b503-2a81ae24cad8
::Version 5 A name-based UID which uses SHA1 hashing.
:: 13726f09-44a9-5eeb-8910-3525a23fb23b
@Echo OFF
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
Set "eval.js=%TEMP%\eval.js"
Set "GetMac=%SystemRoot%\System32\getmac.exe"
For %%1 in ("%*") Do Set "UID=%%~1"
:: To create a UUID:
If /I "%UID%" EQU "/C" (
FSutil ObjectID delete %~f0
For /F "tokens=3 delims=: " %%a in (
'FSutil ObjectID create %~f0^|Find "Object ID"'
) Do Set "UID=%%a"
)
If NOT DEFINED UID (
Echo.Version -2
Echo.Decodes RFC 4122 UUIDs.
Echo.
Echo. %~n0 {[/C] [UUID]}
Echo.
Echo. /C Create a version 1 (timestamp^) UUID.
Echo. UUID A UUID to decode.
Echo.
Echo.The UUID can be in either the string representation format
Echo.
Echo. a32a3277-578c-4da1-b503-2a81ae24cad8
Echo.
Echo.or in the internal format
Echo.
Echo. 77322aa38c57a14db5032a81ae24cad8
Echo.
Echo.Both representations will be displayed. Individual values
Echo.of each component will be displayed below the string
Echo.representation.
Echo.
Echo.When the node is displayed for version 1 UUIDs GETMAC will
Echo.be run to show which of your network adapters is being used
Echo.if that adapter is available to GETMAC.
Goto :EOF
)
Set "xDigit=[0-9a-fA-F]"
Set "REX=^%xDigit%*\-%xDigit%*\-%xDigit%*\-%xDigit%*"
Set "REX=%REX%\-%xDigit%*$"
Echo.%UID%|FindStr "%REX%" >NUL: && (
Set "UID.string=%UID%"
Set "UID=!UID:-=!"
Set "UID.hex=!UID:~6,2!!UID:~4,2!!UID:~2,2!!UID:~0,2!"
Set "UID.hex=!UID.hex!!UID:~10,2!!UID:~8,2!!UID:~14,2!"
Set "UID.hex=!UID.hex!!UID:~12,2!!UID:~16,4!!UID:~20,12!"
Set "UID=!UID.hex!"
) || (Echo.%UID%|FindStr /x "%xDigit%*" >NUL: && (
Set "UID.hex=%UID%"
Set "UID.string=!UID:~6,2!!UID:~4,2!!UID:~2,2!!UID:~0,2!-"
Set "UID.string=!UID.string!!UID:~10,2!!UID:~8,2!-"
Set "UID.string=!UID.string!!UID:~14,2!!UID:~12,2!-"
Set "UID.string=!UID.string!!UID:~16,4!-!UID:~20,12!"
) || (
Echo.INVALID: %UID%
Goto :END
)
)
Set "REX="
Set "index.timeLo=0"
Set "index.timeMi=8"
Set "index.timeHi=12"
Set "index.version=14"
Set "index.variant=16"
Set "index.node=20"
Set /A "variant=0x!UID:~%index.variant%,2!"
Set /A "variant.layout=(variant>>7)&1"
Echo. ********** %UID.hex% **********
Echo.********** %UID.string% **********
Set "NilUUID=%UID:0=%"
If NOT DEFINED NilUUID (
Echo.Nil UUID: All zero UUID.
Goto :END
)
If !variant.layout! EQU 0 (
Set /A "variant.field=0x80, variant.bits=1"
Echo.Variant: Reserved, NCS backward compatibility.
Echo. No decode available.
Goto :END
) Else (
Set /A "variant.layout=(variant>>6)&3"
If !variant.layout! EQU 2 (
Set /A "variant.field=0xC0, variant.bits=2"
) Else (
Set /A "variant.layout=(variant>>5)&7"
Set /A "variant.field=0xE0, variant.bits=3"
If !variant.layout! EQU 6 (
Echo.Variant: Old Microsoft Corporation layout.
Echo. No decode available.
Goto :END
) Else ( REM variant.layout EQU 7
Echo.Variant: Reserved for future definition. We may now be in
Echo. the future but no decode was available at the time
Echo. of this writing.
Goto :END
)
)
)
Set /A "clock.bits=4-variant.bits"
Set /A "version=0x!UID:~%index.version%,1!"
Echo.Variant: %variant.layout%
Echo.Version: %version%
Goto :Version.%version%
:Version.1
Echo.UID Time: %UID.string:~0,14% %UID.string:~15,3%
Echo.Clock Seq: %clock.high%%UID:~18,2%
Echo.Node: %UID:~20,12%
Set "$Short=bits, clock has the lower %clock.bits%."
Echo.Note: Variant has the high %variant.bits% %$Short%
Echo.
:: Change the byte order of the time field:
Set "hex=%UID:~15,1%"
For /L %%i in (12 -2 0) Do Set "hex=!hex!!UID:~%%i,2!"
:: Clock sequence:
Set /A "clock.field=(~variant.field)&0xFF"
Set /A "clock.high=(0x%UID:~16,2%&clock.field)"
Set /A "clock=0x%UID:~18,2%|(clock.high<<8)"
Set /A "clock.high&=0xF0, clock.high>>=4"
Set "clock.high=%clock.high%%UID:~17,1%"
:: Node to display format:
Set /A "node.admin=(%UID:~20,1%>>1)&1"
Set /A "node.cast=(%UID:~20,1%)&1"
Set "node=%UID:~20,2%-%UID:~22,2%-%UID:~24,2%-%UID:~26,2%-"
Set "node=%node%%UID:~28,2%-%UID:~30,2%"
:: Spit out the answers:
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 1: A time-based UUID.
Call :ToTime hex $Time
Echo.UID Time: %$Time%
Set "$Short=This time should be UTC but may be local time on"
Set "$Short=%$Short% systems which do"
Echo. %$Short%
Echo. not have UTC available. On Windows is probably the time
the system
Echo. was last booted. The uniqueness of time is supplemented
by the
Echo. clock sequence presented next.
Echo.Clock Seq: %Clock%
Set /P "=Net node: "<NUL:
CMD/A /C"%GetMAC% /v|FindStr /I /C:"%node%" || Echo.%node%"
If %node.admin% EQU 0 (
Set "node.admin=universally"
) Else (
Set "node.admin=locally"
)
If %node.cast% EQU 1 (
Echo. A false node address created in absence of a network
card.
) Else (
Echo. A %node.admin% administered IEEE 802 EUI-48/MAC-48
address.
)
Goto :END
:Version.2
Echo.Version 2: DCE Security version, with embedded POSIX UIDs. Unable
Echo. to decode this version.
Echo.
Goto :END
:Version.3
Echo.Version 3: A name-based UID which uses MD5 hashing.
Echo. The UUID is the hash.
Echo.
Goto :END
:Version.4
Echo.Version 4: A randomly or pseudo-randomly generated UID.
Echo. The UUID is the random number.
Echo.
Goto :END
:Version.5
Echo.Version 5: A name-based version which uses SHA-1 hashing.
Echo. The UUID is the hash.
Echo.
Goto :END
:Version.6
:Version.7
:Version.8
:Version.9
:Version.10
:Version.11
:Version.12
:Version.13
:Version.14
:Version.15
:Version.0
Echo.Version %version%: This version was not defined when this
Echo.script was written.
Goto :END
:End
If EXIST "%eval.js%" DEL "%eval.js%"
Goto :EOF
:ToTime varnameIN varnameOUT
SetLocal
::These values are all hexadecimal. The math routines speak hex.
::Subtract #Offset from UUID time to make it an NT filetime.
Set "#Offset=0146BF33E42C000"
Set "#To1970=1B21DD213814000"
::PERIOD 100 NANOSECOND INTERVALS
:: HEXADECIMAL DECIMAL
::yearLP 0x11F9AA3308000 (316224000000000)
::year 0x11ED178C6C000 (315360000000000)
::week 0x58028E44000 (6048000000000)
::day 0xC92A69C000 (864000000000)
::hour 0x861C46800 (36000000000)
::minute 0x23C34600 (600000000)
::second 0x989680 (10000000)
Set "$Short=d=new Date((0x!%~1!-0x%#To1970%)/10000);"
Set "$Short=%$Short%[d.getUTCFullYear(),d.getUTCMonth()+1,"
Set "$Short=%$Short%d.getUTCDate(),d.getUTCHours(),d.getUTCMinutes(),
Set "$Short=%$Short%d.getUTCSeconds()]"
Call :eval "%$Short%"
Set "$Time=!eval!"
Set "$Short=(0x!%~1!-0x%#Offset%)"
Call :eval "parseInt(%$Short% %%%% 10000000).toString()"
Set "$ns=000000!eval!" & Set "$ns=!$ns:~-7!"
Set "i=0"
For %%a in (%$Time%) Do Set "$Time.!i!=%%a" & Set /A "i+=1"
For /L %%i in (1,1,5) Do (
Set "$Time.%%i=0!$Time.%%i!"
Set "$Time.%%i=!$Time.%%i:~-2!"
)
Set "$Time=!$Time.0!-!$Time.1!-!$Time.2!
!$Time.3!:!$Time.4!:!$Time.5!.!$ns!"
EndLocal&Set "%~2=%$Time%"
Goto :EOF
:RemoveLeadingZeroes C
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
REM echo on
Set "$C=!%~1!"
If NOT DEFINED $C Set "$C=0"
For /F "tokens=1*" %%1 in (": %$C:0= %") Do Set "$C=%%2"
(
EndLocal
Set "%~1=%$C: =0%"
)
Goto :EOF
:MatchLen varname varname len
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
Set "$A=!%~1!" & Set "$B=!%~2!"
:: REMOVE LEADING ZEROES:
Call :RemoveLeadingZeroes $A
Call :RemoveLeadingZeroes $B
For /F "tokens=1 delims=:" %%a in (
'(echo.%$A%^& echo.^)^|findstr /O .') Do Set /A "$A.len=%%a-3"
For /F "tokens=1 delims=:" %%a in (
'(echo.%$B%^& echo.^)^|findstr /O .') Do Set /A "$B.len=%%a-3"
If %$B.len% LSS %$A.len% (Set "$len=%$A.len%") Else (Set
"$len=%$B.len%")
Set /A "l=$len-1"
REM Echo.Matching: "%$A%" = "%$B%" len=%$len%
If %$B.len% NEQ %$A.len% (
For /L %%i in (%l%, -1, 0) Do (
If "!$A:~%l%,1!" EQU "" Set "$A=0!$A!"
If "!$B:~%l%,1!" EQU "" Set "$B=0!$B!"
)
)
REM Echo.Matched: "%$A%" = "%$B%"
(
EndLocal
Set "%~1=%$A%"
Set "%~1.len=%$A.len%"
Set "%~2=%$B%"
Set "%~2.len=%$B.len%"
Set "%~3=%$Len%"
)
Goto :EOF
:SubtractBigHex a b c
:: 60-bit hexadecimal subtraction:
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
Set "H=0123456789ABCDEF"
Set "$x=0"
Set "$C="
Call :MatchLen %~1 %~2 $len
Set "$A=!%~1!" & Set "$B=!%~2!" & Set /A "$Len-=1"
REM Echo.Subtracting: "%$A%" - "%$B%"
For /L %%i in (%$len%, -1, 0) Do (
Set /A "$1=0x!$A:~%%i,1!-$x, $2=0x!$B:~%%i,1!"
If !$1! LSS !$2! (Set /A "$1+=16, $x=1") Else (Set /A "$x=0")
Set /A "r=$1-$2, c=r/16, r=r%%16, $x-=c"
Call Set "$C=%%H:~!r!,1%%!$C!"
Set "$C=!$i!!$C!"
)
REM Echo.Result: "%$C%"
(
EndLocal
Set "%~3=%$C%"
)
Goto :EOF
:eval expression
:: Prints the mathemagical result the expression.
:: Permits 1024-bit numbers?? ???!
:: Parameters:
:: 1: A math expression.
SetLocal ENABLEEXTENSIONS
If NOT DEFINED eval.js Set "eval.js=%TEMP%\eval.js"
Set "return=%0"
For /F "delims=" %%a in ('Echo.%*') Do (
EndLocal
If NOT EXIST "%eval.js%" (
Echo.WScript.Echo(eval(WScript.Arguments(0^)^)^);>%eval.js%
)
For /F "delims=" %%b in (
'CSCRIPT /NOLOGO /E:JScript "%eval.js%" "%%~a"') Do (
Set "%return:~1%=%%b"
)
REM To DEL, or not to DEL: that is the question:
REM Whether 'tis nobler in the mind to suffer
REM The bits and bytes of wasted space,
REM Or to take arms against a sea of files,
REM And by opposing end them? To DEL: to clean;
REM No more; and by cleaning to say we end
REM The corruption and fragmentation
REM That disks are heir to, 'tis a consummation
REM Devoutly to be wish'd. To DEL, to clean;
REM To clean: perchance to free: ay, there's the rub;
REM For in that cleaning of DEL what freeing may come
REM When we have shuffled off this magnetic spoil,
REM Must give us PAUSE: there's the respect ...
REM DEL "%eval.js%"
)
Goto :EOF
> Echo. %$Short%
> Echo. not have UTC available. On Windows is probably the
> time the system
> Echo. was last booted. The uniqueness of time is
> supplemented by the
> Echo. clock sequence presented next.
I neglected some long lines. There are more than just those two that got
wrapped. It will take a little work to make the script usable. I should
make a TIE format to handle script uploads.
Frank
> I neglected some long lines. There are more than just those two that
> got wrapped.
a "time-honored" :-) way in these newsgroups to make wrapped lines in
scripts stand out is to precede any new line with two blanks. A line
starting at the left margin then has wrapped.
--
Herzliche Gr��e,
Klaus Meinhard
> a "time-honored" :-) way in these newsgroups to make wrapped
> lines in scripts stand out is to precede any new line with
> two blanks.
The name is familiar. I think you have been in this group for a long
time. If so, you might recall that it was I who set that "time-honored"
precedent. I am certainly not the first to have indented code for
clarity, but with its benefit and by my volume it became accepted here.
I don't believe a user should have to cut numbers from each line to make
a script work.
But with large scripts I now prefer to send them as a seperate message
in the thread and to announce them in a preceeding message so that
people may avoid the script if they aren't interested. Also, my intent
is that the message containing the script should be properly formatted
and usable as is, so that a person need only CTRL-A, CTRL-C, then CTRL-V
into a new file. My subject line on those messages is normally the
filename that I use locally.
I consider that the long lines in DecodeUID.cmd are errors; a failure by
me. But there are actually only four lines which need to be fixed so I
don't intend to send a fixed copy unless it is requested. I don't like
to repetively send large scripts with only minor changes. It's excessive
and it's a burden on the group.
I still indent scripts which are written in messages contaiining other
matter.
Previously the word wrap on my messages was set to 144 columns and this
was a problem for people with news-readers which did not wrap text into
the display, so I changed it to 72. I think the reason those readers
don't wrap is because some text shouldn't be wrapped; it should be a
certain specific length and the author is expected to wrap where
necessary. Scripts are one of those items which should not be wrapped.
So my intent now, if I can make it work, is that my right margin will be
72 for all messages except those which contain only a script. I think
the maximum line length for e-mail is 1024 so I'll probably set my
script margin to about half of that.
Frank
> ... you might recall that it was I who set that "time-honored"
> precedent. I am certainly not the first ...
After looking back I found that Tom Lavedas, Klaus Meinhard, and Ted
[Gearbox] Davis were here more than a year before I got here, but it was
Tom Lavedas who was indenting regularly with two spaces so I got it from
him. Sorry Tom. Rarely do I try to claim credit for anything because
it's too easy too be wrong like that.
Frank
- Fixes where they seemed necessary.
- Improved input validation.
- Ability to create UUIDs of version 1 (time/node). Saves and restores
any previously existing UUID on the script file.
- Ability to create UUIDs of version 4 (random).
The script will also be sent with the right margin set to column 132,
the maximum with my software. In the script the lines were not shortened
unless they exceeded 130 characters. When viewing the script in a window
the lines may be wrapped in the display, but if copied (CTRL-C) and
pasted (CTRL-V) into a text editor they should be their full length.
Please let me know if there are any problems with my transmission or
with long lines being wrapped in reception. Google should not be a
problem because they allow access to the raw file.
Frank
::Version 1 A time-based UID.
:: 2b422150-d42b-11de-8a39-0800200c9a66
:: 2fac1234-31f8-11b4-a222-08002b34c003
::Version 2 A DCE Security version, with embedded POSIX UIDs.
:: 2b422150-d42b-21de-8039-0800200c9a66 (uncertain construct)
::Version 3 A name-based UID which uses MD5 hashing.
:: A2E3D453-6AF6-304A-94F5-017024598F63
:: e902893a-9d22-3c7e-a7b8-d6e313b71d9f
::Version 4 A randomly or pseudo-randomly generated UID.
:: f47ac10b-58cc-4372-a567-0e02b2c3d479
:: 127FB026-B05D-4783-A810-B7A69DA6C96C
:: a32a3277-578c-4da1-b503-2a81ae24cad8
::Version 5 A name-based UID which uses SHA1 hashing.
:: 13726f09-44a9-5eeb-8910-3525a23fb23b
:: ^
:: Note that this | is the version number column.
@Echo OFF
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:: Clear environment:
Set "DATE=" & Set "TIME=" & Set "CD=" & Set "RANDOM="
For /F "tokens=1* delims==" %%a in ('Set "$" 2^>NUL:') Do Set "%%a="
For /F "tokens=1* delims==" %%a in ('Set "#" 2^>NUL:') Do Set "%%a="
:: Set constants:
Set "#MY=%temp%\%~n0.%RANDOM%%TIME:~-2%"
Set "#eval.js=%#MY%\eval.js"
Set "#GetMac=%SystemRoot%\System32\getmac.exe"
::Set "#index.timeLo=0"
::Set "#index.timeMi=8"
::Set "#index.timeHi=12"
::Set "#index.version=14"
::Set "#index.variant=16"
::Set "#index.node=20"
Set "$UID="
For %%1 in ("%*") Do Set "$UID=%%~1"
:: To create a UUID:
If /I "%$UID%" EQU "/C" ( Call :GetUUID1
) Else If "%$UID%" EQU "/1" ( Call :GetUUID1
) Else If "%$UID%" EQU "/4" ( Call :GetUUID4)
If NOT DEFINED $UID (
Echo.Version -1
Echo.Decodes RFC 4122 UUIDs.
Echo.
Echo. %~n0 {[/1] [/4] [UUID]}
Echo.
Echo. /1 Create a version 1 (timestamp^) UUID.
Echo. /4 Create a version 4 (random^) UUID.
REM /C is still enabled but not advertised. Use /1 instead.
REM Echo. /C Create a version 1 (timestamp^) UUID.
Echo. UUID A UUID to decode.
Echo.
Echo.The UUID can be in either the string representation format
Echo.
Echo. a1a2a3a4-b1b2-c1c2-d1e2-f1f2f3f4f5f6
Echo.
Echo.or in the internal format
Echo.
Echo. a4a3a2a1b2b1c2c1d1e2f1f2f3f4f5f6
Echo.
Echo.Both representations will be displayed. Individual values of each component
Echo.will be displayed below the string representation.
Goto :EOF
)
Set "#xDigit=[0-9a-fA-F]"
Echo.%$UID%|FindStr "^%#xDigit%*\-%#xDigit%*\-%#xDigit%*\-%#xDigit%*\-%#xDigit%*$" >NUL: && (
If "%$UID:~35%" EQU "" (Goto :Invalid) Else If "%$UID:~36%" NEQ "" (Goto :Invalid)
For %%i in (8 13 18 23) Do If "!$UID:~%%i,1!" NEQ "-" Goto :Invalid
Set "$UID.string=%$UID%"
Set "$UID=!$UID:-=!"
Set "$UID.hex=!$UID:~6,2!!$UID:~4,2!!$UID:~2,2!!$UID:~0,2!!$UID:~10,2!!$UID:~8,2!!$UID:~14,2!!$UID:~12,2!"
Set "$UID.hex=!$UID.hex!!$UID:~16,4!!$UID:~20,12!"
Set "$UID=!$UID.hex!"
) || (Echo.%$UID%|FindStr /x "%#xDigit%*" >NUL: && (
If "%$UID:~31%" EQU "" (Goto :Invalid) Else If "%$UID:~32%" NEQ "" (Goto :Invalid)
Set "$UID.hex=%$UID%"
Set "$UID.string=!$UID:~6,2!!$UID:~4,2!!$UID:~2,2!!$UID:~0,2!-!$UID:~10,2!!$UID:~8,2!-!$UID:~14,2!!$UID:~12,2!-!$UID:~16,4!"
Set "$UID.string=!$UID.string!-!$UID:~20,12!"
) || (
Goto :Invalid
)
)
Set "#xDigit="
MkDir "%#MY%"
Set /A "$variant=0x!$UID:~16,2!"
Set /A "$variant.layout=($variant>>7)&1"
Echo. ********** %$UID.hex% **********
Echo.********** %$UID.string% **********
If !$variant.layout! EQU 0 (
Set /A "$variant.field=0x80, $variant.bits=1"
Set "NilUUID=%$UID:0=%"
If NOT DEFINED NilUUID (
Echo.Variant: A nil UUID.
Echo.Version 0: A special form of UUID that is specified to have all 128 bits set to zero.
Echo. zero.
) Else Echo.Variant: Reserved, NCS backward compatibility. No decode available.
Goto :END
) Else (
Set /A "$variant.layout=($variant>>6)&3"
If !$variant.layout! EQU 2 (
Set /A "$variant.field=0xC0, $variant.bits=2"
) Else (
Set /A "$variant.layout=($variant>>5)&7"
Set /A "$variant.field=0xE0, $variant.bits=3"
If !$variant.layout! EQU 6 (
Echo.Variant: Old Microsoft Corporation layout. No decode available.
Goto :END
) Else ( REM variant.layout EQU 7
Echo.Variant: Reserved for future definition. We may now be in the future but no
Echo. decode was available at the time of this writing.
Goto :END
)
)
)
Set /A "$clock.bits=4-$variant.bits"
Set /A "$version=0x!$UID:~14,1!"
Echo.Variant: %$variant.layout%
Echo.Version: %$version%
Goto :Version.%$version%
:CommonV1V2
:: Change the byte order of the time field:
Set "$hex=%$UID:~15,1%"
For /L %%i in (12 -2 0) Do Set "$hex=!$hex!!$UID:~%%i,2!"
:: Node to display format:
Set /A "$node.admin=(%$UID:~20,1%>>1)&1"
Set /A "$node.cast=(%$UID:~20,1%)&1"
Set "$node=%$UID:~20,2%-%$UID:~22,2%-%$UID:~24,2%-%$UID:~26,2%-"
Set "$node=%$node%%$UID:~28,2%-%$UID:~30,2%"
If %$node.admin% EQU 0 (
Set "$node.admin=universally"
) Else (
Set "$node.admin=locally"
)
Goto :EOF
:ShowNode
Set /P "=Net node: "<NUL:
CMD/A /C"%#GetMAC% /v|FindStr /I /C:"%$node%" || Echo.%$node%"
If %$node.cast% EQU 1 (
Echo. A false node address created in absence of a network card.
) Else (
Echo. A %$node.admin% administered IEEE 802 EUI-48/MAC-48 address.
)
Goto :EOF
:Version.1
Call :CommonV1V2
:: Clock sequence:
Set /A "$clock.field=(~$variant.field)&0xFF"
Set /A "$clock.high=(0x%$UID:~16,2%&$clock.field)"
Set /A "$clock=0x%$UID:~18,2%|($clock.high<<8)"
Set /A "$clock.high&=0xF0, $clock.high>>=4"
Set "$clock.high=%$clock.high%%$UID:~17,1%"
Call :ToTime hex $Time
Echo.UID Time: %$UID.string:~0,14% %$UID.string:~15,3%
Echo.Clock Seq: %$clock.high%%$UID:~18,2%
Echo.Node: %$UID:~20,12%
Echo.Note: Variant has the high %variant.bits% bits, clock has the lower %clock.bits%.
Echo.
:: Spit out the answers:
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 1: A time-based UUID.
Echo.UID Time: %$Time%
Echo. This time should be UTC but may be local time on systems which do
Echo. not have UTC available. On Windows is probably the time the system
Echo. was last booted. The uniqueness of time is supplemented by the
Echo. clock sequence presented next.
Echo.Clock Seq: %$Clock%
Call :ShowNode
Goto :END
:Version.2
REM clock_seq_low:
REM typedef signed32 sec_rgy_domain_t;
REM const signed32 sec_rgy_domain_person = 0;//"POSIX UID domain"
REM const signed32 sec_rgy_domain_group = 1;//"POSIX GID domain"
REM const signed32 sec_rgy_domain_org = 2; // Should not get this.
Call :CommonV1V2
:: Clock sequence:
Set /A "$clock.high=0x%$UID:~17,1%, $Clock=0x%$UID:~18,2%, $=$clock.high+1"
For /F "tokens=%$%" %%a in ("U G O") Do Set "$Posix=%%aID"
Set "$hex=%$hex:~0,7%00000000"
Call :ToTime $hex $Time
Echo.POSIX %$Posix%: %$UID.string:~0,8%
Echo.UID Time: %$UID.string:~9,4% %$UID.string:~15,3%
Echo.Domain: %$clock.high%
Echo.Clock Seq: %$UID:~18,2%
Echo.Node: %$UID:~20,12%
Echo.Note: Variant has the high %$variant.bits% bits, clock has the lower %$clock.bits%.
Echo.
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 2: DCE Security version, with embedded POSIX UIDs. Unable to decode
Echo. this version with any certainty. This is only a guess.
Echo.UID Time: %$Time%
Echo. The time for this version UUID is only the upper 4 bytes.
Echo.Clock Seq: %$Clock%
Call :ShowNode
Goto :END
:Version.3
Echo.
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 3: A name-based UID which uses MD5 hashing. The UUID is the hash.
Goto :END
:Version.4
Echo.
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 4: A randomly or pseudo-randomly generated UID. The UUID is the number.
Goto :END
:Version.5
Echo.
Echo.Variant: A UUID layout specified by RFC 4122.
Echo.Version 5: A name-based version which uses SHA-1 hashing. The UUID is the hash.
Goto :END
:Version.6
:Version.7
:Version.8
:Version.9
:Version.10
:Version.11
:Version.12
:Version.13
:Version.14
:Version.15
:Version.0
Echo.
Echo.Version %$version%: This version was not defined when this script was written.
Goto :END
:Invalid
Echo.The UUID is invalid. It must be 32 characters in one of these two forms: >&2
Echo. a1a2a3a4-b1b2-c1c2-d1e1-f1f2f3f4f5f6 >&2
Echo. a4a3a2a1b2b1c2c1d1e1e1f2f3f4f5f6 >&2
Exit /B 1
:END
If EXIST "%#eval.js%" DEL "%#eval.js%"
If EXIST "%#MY%" RD /S /Q "%#MY%"
REM ....'....1....'....2....'....3....'....4....'....5....'....6....'....7....'....8
Goto :EOF
:ToTime varnameIN varnameOUT
SetLocal ENABLEEXTENSIONS
::These values are all hexadecimal. The math routines speak hex.
::Subtract #Offset from UUID time to make it an NT filetime.
Set "#Offset=0146BF33E42C000"
Set "#To1970=1B21DD213814000"
::PERIOD 100 NANOSECOND INTERVALS
:: HEXADECIMAL DECIMAL
::yearLP 0x11F9AA3308000 (316224000000000)
::year 0x11ED178C6C000 (315360000000000)
::week 0x58028E44000 (6048000000000)
::day 0xC92A69C000 (864000000000)
::hour 0x861C46800 (36000000000)
::minute 0x23C34600 (600000000)
::second 0x989680 (10000000)
Set "$Short=[d.getUTCFullYear(),d.getUTCMonth()+1,d.getUTCDate(),d.getUTCHours(),d.getUTCMinutes(),d.getUTCSeconds()]"
Call :eval "d=new Date((0x!%~1!-0x%#To1970%)/10000);%$Short%"
Set "$Time=!eval!"
Call :eval "parseInt((0x!%~1!-0x%#Offset%) %%%% 10000000).toString()"
Set "$ns=000000!eval!" & Set "$ns=!$ns:~-7!"
Set "$=0"
For %%a in (%$Time%) Do Set "$Time.!$!=%%a" & Set /A "$+=1"
For /L %%i in (1,1,5) Do (
Set "$Time.%%i=0!$Time.%%i!"
Set "$Time.%%i=!$Time.%%i:~-2!"
)
Set "$Time=!$Time.0!-!$Time.1!-!$Time.2! !$Time.3!:!$Time.4!:!$Time.5!.!$ns!"
EndLocal&Set "%~2=%$Time%"
Goto :EOF
:eval expression
:: Prints the mathemagical result of the expression.
:: Permits 1024-bit numbers?? ???!
:: Parameters:
:: 1: A math expression.
SetLocal ENABLEEXTENSIONS
If NOT DEFINED #eval.js Set "#eval.js=%TEMP%\eval.js"
Set "$return=%0"
For /F "delims=" %%a in ('Echo.%*') Do (
EndLocal
If NOT EXIST "%#eval.js%" (
Echo.WScript.Echo(eval(WScript.Arguments(0^)^)^);>%#eval.js%
)
For /F "delims=" %%b in (
'CSCRIPT /NOLOGO /E:JScript "%#eval.js%" "%%~a"') Do (
Set "%$return:~1%=%%b"
)
REM To DEL, or not to DEL: that is the question:
REM Whether 'tis nobler in the mind to suffer
REM The bits and bytes of wasted space,
REM Or to take arms against a sea of files,
REM And by opposing end them? To DEL: to clean;
REM No more; and by cleaning to say we end
REM The corruption and fragmentation
REM That disks are heir to, 'tis a consummation
REM Devoutly to be wish'd. To DEL, to clean;
REM To clean: perchance to free: ay, there's the rub;
REM For in that cleaning of DEL what freeing may come
REM When we have shuffled off this magnetic spoil,
REM Must give us PAUSE: there's the respect ...
REM DEL "%#eval.js%"
)
Goto :EOF
:GetUUID1
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
Set "$UID=" & Set "$ObjectID="
FSutil ObjectID query %~f0 >NUL:
If %ErrorLevel% EQU 0 (
REM Save IDs if they exist.
Set "$ObjectID=TRUE" & Set "$=0"
For /F "tokens=2 delims=:" %%2 in ('FSutil ObjectID create %~f0') Do (
Set /A "$+=1"
Set "$UID.!$!=%%2"
)
FSutil ObjectID delete %~f0
)
For /F "tokens=2 delims=:" %%2 in (
'FSutil ObjectID create %~f0'
) Do (If NOT DEFINED $UID (For %%a in (%%2) Do Set "$UID=%%a"))
FSutil ObjectID delete %~f0
If DEFINED $ObjectID (
REM Restore original IDs.
FSutil ObjectID set %$UID.1% %$UID.2% %$UID.3% %$UID.4% %~f0
)
EndLocal & Set "$UID=%$UID%"
Goto :EOF
:GetUUID4
:: Todd Vargo, 2009-11-17; altered 2009-11-18,20 FPW
SetLocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
Set "RANDOM=" & Set "TIME=" & Set "$UID="
Set "$chrs=0123456789ABCDEF"
For /L %%i in (0,1,31) Do (
If %%i EQU 14 (Set "$num=4") Else (
Set /A "$num=(!RANDOM!+1!TIME:~-2!) %% 16"
If %%i EQU 16 Set /A "$num=0x8 | ($num&0x3)"
)
Call Set $UID=!$UID!%%$chrs:~!$num!,1%%
)
EndLocal & Set "$UID=%$UID%"
Goto :EOF