0

Let's say we have a string

"{GUID}"

wherein GUID is a standard GUID in {}. I need to get a variable of type GUID matching the given string. It is to be done with visual C++ and the version is very old (6.0) if that matters.

Firstly I tried to use GUIDFromString function but wasn't able to get it imported so found out about UuidFromString. But I am really stuck at all these casts from unsigned char to char etc, having no C++ background it is very hard. Maybe some one will be so kind to help me with this. Thanks.

Gonzalez
  • 681
  • 1
  • 11
  • 21
  • While I know almost nothing about Windows programming, [Raymond Chen wrote about this recently](https://blogs.msdn.microsoft.com/oldnewthing/20160331-00/?p=93231). – BoBTFish Apr 11 '16 at 14:26
  • First upgrade your compiler than comeback here. That compiler is buggy, and incompatible with modern features that are thread-safe. Go! – Joel Apr 11 '16 at 14:26
  • @Joel2 Do you really think I don't know about the new versions of compiler? If upgrading was an option I'd do it, but it is not. Discussing reasons would be much of an off-topic, but in general I am dealing with a legacy project where I should change very few things, so bringing it to be compatible with the current VS would require a lot of time and expertise. – Gonzalez Apr 11 '16 at 14:31

2 Answers2

1

GUID refers to some unique identification number, which can be generated using some algorithm - you can find some descriptions on Microsoft's algorithms - where they try to pick up timestamp, network card number, and on one, and mix up into one unique GUID.

What I have checked - noone prevents you of creating your own "unique" generation algorithm - but you need to somehow ensure that your unique generation algorithm won't collide with existing algorithms, which is highly unlikely. Also GUID's generated by your algorithm should not also collide with your own GUID's.

While browsing internet I have found some approaches to generate such guid - for example - Microsoft Office: http://support.microsoft.com/kb/2186281

When generating GUID from Strings, you can use either String.GetHashCode32 or even calculate for example 20 byte sha-1 hash over string. (First one is easier, but second creates more bytes to use for GUID).

And then start to fill in GUID, as much as it requires it.

Here is some demo code which let's you get to the idea:

using System;

class Program
{
    /// <summary>
    /// http://stackoverflow.com/questions/53086/can-i-depend-on-the-values-of-gethashcode-to-be-consistent
    /// 
    /// Similar to String.GetHashCode but returns the same as the x86 version of String.GetHashCode for x64 and x86 frameworks.
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static unsafe int GetHashCode32(string s)
    {
        fixed (char* str = s.ToCharArray())
        {
            char* chPtr = str;
            int num = 0x15051505;
            int num2 = num;
            int* numPtr = (int*)chPtr;
            for (int i = s.Length; i > 0; i -= 4)
            {
                num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
                if (i <= 2)
                {
                    break;
                }
                num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
                numPtr += 2;
            }
            return (num + (num2 * 0x5d588b65));
        }
    }
    /// <summary>
    /// Generates new product code for particular product / install package.
    /// </summary>
    /// <param name="productName">Logical product name for which to generate</param>
    /// <param name="productVersion">Product version in form "1.0.0"</param>
    /// <returns></returns>
    static public String GenerateProductCode( String productName, String productVersion )
    {
        String[] vparts = productVersion.Split(".".ToCharArray());
        int[] verParts = new int [3] { 1, 0, 0 };
        int i = 0; 
        foreach( String v in vparts )
        {
            Int32.TryParse(v, out verParts[i++] );
            if( i >= 3 ) break;
        }

        //
        //  "MyCompanyName", "1.0.2" will generate guid like this: {F974DC1F-0001-0000-0002-10009CD45A98}
        //                                                         ^ Hash over manufacturer name - "MyCompanyName"
        //                                                                  ^ Version - "<major>-<minor>-<build>" in hexadecimal
        //                                                                                 ^ 1 as for 64 bit.
        //                                                                                  ^000 - just reserved for future needs
        //                                                                                     ^ Hash over product name
        //
        //  See also similar generation schemes - http://support.microsoft.com/kb/2186281.
        //
        String newGuid = String.Format("{0:X8}-{1:X4}-{2:X4}-{3:X4}-1000{4:X8}", GetHashCode32("MyCompanyName"), verParts[0], verParts[1], verParts[2], GetHashCode32(productName));
        newGuid = "{" + newGuid + "}";
        return newGuid;
    }

    static void Main()
    {
        String s = GenerateProductCode("MyProduct", "1.0.2");
        Console.WriteLine(s);
    }
}

Will print out:

{F974DC1F-0001-0000-0002-10003618D1E1}

But in similar manner you can generate GUIDs in C++ as well - use sprintf() most probably.

Here is .NET compatible function for converting String into hash code:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>


int GetHashCode32( const wchar_t* ps )
{
    int num = 0x15051505;
    int num2 = num;
    const wchar_t* s = ps;
    const char* chPtr=(const char*) ps;
    size_t numBuff = wcslen((wchar_t*) chPtr) * 2;
    int* numPtr = (int*)chPtr;

    for (int i = wcslen(s); i > 0; i -= 4)
    {
        num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
        if (i <= 2)
        {
            break;
        }
        num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
        numPtr += 2;
    }

    return (num + (num2 * 0x5d588b65));
}

void GetHash(const wchar_t* p)
{
    printf("'%S' = %08X", p, GetHashCode32(p));
    printf("\r\n");
}



void main(void)
{
    GetHash(L"testing");
    GetHash(L"MainClass::" __FUNCTIONW__);
    GetHash(L"1");
    GetHash(L"");

}
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
1

Okay, the problem was in include and libs. You need to include <Rpc.h> and link the RPC library:

#pragma comment (lib, "Rpcrt4.lib")

And than you can use UuidFromString function. Just note that you don't need to include { and } in your string representation.

Gonzalez
  • 681
  • 1
  • 11
  • 21