Important alert: (current site time 10/24/2014 5:55:31 AM EDT)
 

article

Smallest but fastest GUID generator function (using API)

Email
Submitted on: 12/6/2012 3:14:47 PM
By: Bonnie West 
Level: Beginner
User Rating: By 10 Users
Compatibility: VB 5.0, VB 6.0
Views: 18474
(About the author)
 
     

This details how the shortest CreateGUID function that uses API achieves its impressive speed. The included simple benchmark module pits it against other GUID generating routines.



This article has accompanying files
 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
  1. You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
				





An API-based CreateGUID function requires at the very least a single API function
call. The CoCreateGuid function seems to be the most popular API used for this
task. However, as the remarks in its documentation points out, it in fact calls
another API to do the real job. The RPC function UuidCreate generates the actual
Universally Unique Identifiers (UUID), which Microsoft has implemented as the GUID.

Manually converting the GUID/UUID structure to a String can be quite cumbersome
to do in VB. Fortunately, two APIs already exists for this purpose: the
UuidToString function and the StringFromGUID2 function. One drawback when using
UuidToString is that the function RpcStringFree needs to be called to release the
memory allocated by the RPC run-time library. StringFromGUID2, on the other hand,
just needs to be provided a buffer to which it will write the results.
StringFromGUID2 does have a limitation though, in that it only works with Unicode
strings. But that is easily resolved by declaring the lpsz parameter As Long and
by using StrPtr.

When allocating buffers, the intrinsic VB functions Space$ and String$ are often
used. It has already been proven that Space$ is the faster of the two. But if
utmost speed is a major factor, then SysAllocStringLen/SysReAllocStringLen are
the functions to call. While writing a Declare statement for SysAllocStringLen
that returns a "proper" VB String looks impossible (it is best called from a
Type Library), SysReAllocStringLen's syntax, on the other hand, is much easier
to convert.

Here are the necessary API declarations:

Private Type UUID
    Data1    As Long
    Data2    As Integer
    Data3    As Integer
    Data4(7) As Byte
End Type
Private Declare Function
UuidCreate Lib "rpcrt4.dll" ( _     ByRef lpUuid As Any _ ) As Long Private Declare Function StringFromGUID2 Lib "ole32.dll" ( _     ByRef rguid As Any, _     ByVal lpsz As Long, _     ByVal cchMax As Long _ ) As Long Private Declare Function SysReAllocStringLen Lib "oleaut32.dll" ( _     ByVal pBSTR As Long, _     Optional ByVal pszStrPtr As Long, _     Optional ByVal Length As Long _ ) As Long

UuidCreate's lpUuid parameter is typed As Any to allow either GUID or UUID
structures (which are identical) or even Long Arrays. The same thing is done to
StringFromGUID2's rguid argument.

SysReAllocStringLen's first parameter should be passed a pointer to a BSTR.
Because VB Strings are also known as BSTRs, a String variable's address is
therefore retrieved with VarPtr. The second parameter, on the other hand, should
be passed a pointer to some other string's contents, i.e., with StrPtr. If this
parameter is skipped, SysReAllocStringLen will not initialize the data; thus the
resulting string will contain garbage. The final optional parameter specifies how
large the new string will be. If not given, a zero-length string ("") will be
returned.

And now, for the CreateGUID function:

Public Function CreateGUID() As String
    Const RPC_S_OK = 0&: Dim udtUUID As UUID
    If UuidCreate(udtUUID) = RPC_S_OK Then _     SysReAllocStringLen VarPtr(CreateGUID), , 38&: _     StringFromGUID2 udtUUID, StrPtr(CreateGUID), 39& End Function

If UuidCreate returns successfully, then the implicit function variable is used
as a buffer and allocated with the exact size required (SysReAllocStringLen
appends a Null character before returning the string). By not specifying a string
to copy from, SysReAllocStringLen leaves the output string uninitialized. This
method makes it faster than using the Space$ function. Finally, StringFromGUID2
writes the converted value into the supplied buffer, which now becomes
CreateGUID's return value.





The included benchmark module compares the performance of this function against
several other GUID functions from this site, as well as from two other.



winzip iconDownload article

Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.Virus note:All files are scanned once-a-day by Planet Source Code for viruses, but new viruses come out every day, so no prevention program can catch 100% of them. For your own safety, please:
  1. Re-scan downloaded files using your personal virus checker before using it.
  2. NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.
  3. Scan the source code with Minnow's Project Scanner

If you don't have a virus scanner, you can get one at many places on the net including:McAfee.com

 
Terms of Agreement:   
By using this article, you agree to the following terms...   
  1. You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.


Other 9 submission(s) by this author

 


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this article (in the Beginner category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments

10/15/2012 4:13:47 AMDave Carter

Thanks Bonnie :)
(If this comment was disrespectful, please report it.)

 
11/3/2012 4:14:38 PMThePiper

Thanks! I like this kind of instructive studies.
(If this comment was disrespectful, please report it.)

 
11/8/2012 2:55:14 AMBonnie West

Thank you too, both of you!
More interesting codes are on the way...
(If this comment was disrespectful, please report it.)

 
11/19/2012 9:53:28 AMC. Sibon

Very handy indeed! thanks and good luck.
(If this comment was disrespectful, please report it.)

 
3/7/2013 2:39:42 AMkazemtnt

Thank's
(If this comment was disrespectful, please report it.)

 
10/6/2013 5:10:10 AMRde

Hi Bonnie

I'm impressed to see your take on the sysallocstr functions, the best minds in VB felt these were out of reach, and only allocbytelen became accessable from within VB.

Now you have come up with the holy grail - allocate a string without initialising it all from within VB!

Love your work,
and happy coding from Rd.
(If this comment was disrespectful, please report it.)

 
10/14/2013 10:43:34 AMBonnie West

Thanks a lot, Rde!

I was only able to figure it out because I got inspired by your TLB declares for the Sys*AllocString* functions. I would have never figured it out otherwise! So, thanks again!

BTW, I'm also a fan of your codes!
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular article, please click here instead.)
 

To post feedback, first please login.