| 1 | // Licensed to the .NET Foundation under one or more agreements. | 
|---|
| 2 | // The .NET Foundation licenses this file to you under the MIT license. | 
|---|
| 3 | // See the LICENSE file in the project root for more information. | 
|---|
| 4 |  | 
|---|
| 5 | // GuidFromName | 
|---|
| 6 |  | 
|---|
| 7 | /** | 
|---|
| 8 |  | 
|---|
| 9 | Algorithm from Internet Draft document "UUIDs and GUIDs" | 
|---|
| 10 | By Paul J. Leach and Rich Sals, February 4, 1998. | 
|---|
| 11 |  | 
|---|
| 12 | This function has been adapted from the routines in the document | 
|---|
| 13 | uuid_create_from_name and format_uuid_v3 | 
|---|
| 14 |  | 
|---|
| 15 | Changes from documented routines: | 
|---|
| 16 | 1. Changed all instances of uuid_t to GUID. | 
|---|
| 17 | uuid_t field time_low is GUID field Data1. | 
|---|
| 18 | uuid_t field time_mid is GUID field Data2. | 
|---|
| 19 | uuid_t field time_hi_and_version is GUID field Data3. | 
|---|
| 20 | uuid_t field clock_seq_hi_and_reserved is GUID field Data4[0]. | 
|---|
| 21 | uuid_t field clock_seq_low is GUID field Data4[1]. | 
|---|
| 22 | uuid_t field node[6] is GUID field Data4[2] through Data4[8]. | 
|---|
| 23 |  | 
|---|
| 24 | 2. Use a c++ implementation of the md5 cryptographic hash function. | 
|---|
| 25 |  | 
|---|
| 26 | 3. Implemented the htonl, htons, ntohl, ntohs socket routines as inlines. | 
|---|
| 27 |  | 
|---|
| 28 | 4. Renamed variables and types to suit my biases. | 
|---|
| 29 |  | 
|---|
| 30 |  | 
|---|
| 31 | Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. | 
|---|
| 32 | Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & | 
|---|
| 33 | Digital Equipment Corporation, Maynard, Mass. | 
|---|
| 34 | To anyone who acknowledges that this file is provided "AS IS" | 
|---|
| 35 | without any express or implied warranty: permission to use, copy, | 
|---|
| 36 | modify, and distribute this file for any purpose is hereby | 
|---|
| 37 | granted without fee, provided that the above copyright notices and | 
|---|
| 38 | this notice appears in all source code copies, and that none of | 
|---|
| 39 | the names of Open Software Foundation, Inc., Hewlett-Packard | 
|---|
| 40 | Company, or Digital Equipment Corporation be used in advertising | 
|---|
| 41 | or publicity pertaining to distribution of the software without | 
|---|
| 42 | specific, written prior permission.  Neither Open Software | 
|---|
| 43 | Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment | 
|---|
| 44 | Corporation makes any representations about the suitability of | 
|---|
| 45 | this software for any purpose. | 
|---|
| 46 |  | 
|---|
| 47 |  | 
|---|
| 48 | Copyright(C) The Internet Society 1997. All Rights Reserved. | 
|---|
| 49 |  | 
|---|
| 50 | This document and translations of it may be copied and furnished to others, | 
|---|
| 51 | and derivative works that comment on or otherwise explain it or assist in | 
|---|
| 52 | its implementation may be prepared, copied, published and distributed, in | 
|---|
| 53 | whole or in part, without restriction of any kind, provided that the above | 
|---|
| 54 | copyright notice and this paragraph are included on all such copies and | 
|---|
| 55 | derivative works.However, this document itself may not be modified in any | 
|---|
| 56 | way, such as by removing the copyright notice or references to the Internet | 
|---|
| 57 | Society or other Internet organizations, except as needed for the purpose of | 
|---|
| 58 | developing Internet standards in which case the procedures for copyrights | 
|---|
| 59 | defined in the Internet Standards process must be followed, or as required | 
|---|
| 60 | to translate it into languages other than English. | 
|---|
| 61 |  | 
|---|
| 62 | The limited permissions granted above are perpetual and will not be revoked | 
|---|
| 63 | by the Internet Society or its successors or assigns. | 
|---|
| 64 |  | 
|---|
| 65 | This document and the information contained herein is provided on an "AS IS" | 
|---|
| 66 | basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE | 
|---|
| 67 | DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | 
|---|
| 68 | ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY | 
|---|
| 69 | RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A | 
|---|
| 70 | PARTICULAR PURPOSE. | 
|---|
| 71 |  | 
|---|
| 72 | */ | 
|---|
| 73 |  | 
|---|
| 74 | #include "stdafx.h" | 
|---|
| 75 |  | 
|---|
| 76 | #include "md5.h"                // cryptographic hash function | 
|---|
| 77 | #include "guidfromname.h"       // verify our function signature | 
|---|
| 78 | #include "contract.h" | 
|---|
| 79 |  | 
|---|
| 80 | #if BIGENDIAN | 
|---|
| 81 | #define BigEndian() true | 
|---|
| 82 | #else | 
|---|
| 83 | #define BigEndian() false | 
|---|
| 84 | #endif | 
|---|
| 85 |  | 
|---|
| 86 | //============================================================================= | 
|---|
| 87 | // htons, htonl, ntohs, ntohl equivalents copied and adapted from socket library. | 
|---|
| 88 | //============================================================================= | 
|---|
| 89 |  | 
|---|
| 90 | // HostToNetworkLong converts a 32-bit long to network byte order | 
|---|
| 91 |  | 
|---|
| 92 | inline ULONG HostToNetworkLong(ULONG hostlong) | 
|---|
| 93 | { | 
|---|
| 94 | LIMITED_METHOD_CONTRACT; | 
|---|
| 95 |  | 
|---|
| 96 | if (BigEndian()) | 
|---|
| 97 | return hostlong; | 
|---|
| 98 | else | 
|---|
| 99 | return  ( (hostlong >> 24) & 0x000000FFL) | | 
|---|
| 100 | ( (hostlong >>  8) & 0x0000FF00L) | | 
|---|
| 101 | ( (hostlong <<  8) & 0x00FF0000L) | | 
|---|
| 102 | ( (hostlong << 24) & 0xFF000000L); | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | // HostToNetworkLong converts a 16-bit short to network byte order | 
|---|
| 106 |  | 
|---|
| 107 | inline USHORT HostToNetworkShort(USHORT hostshort) | 
|---|
| 108 | { | 
|---|
| 109 | LIMITED_METHOD_CONTRACT; | 
|---|
| 110 |  | 
|---|
| 111 | if (BigEndian()) | 
|---|
| 112 | return hostshort; | 
|---|
| 113 | else | 
|---|
| 114 | return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00); | 
|---|
| 115 | } | 
|---|
| 116 |  | 
|---|
| 117 | // NetworkToHostLong converts a 32-bit long to local host byte order | 
|---|
| 118 |  | 
|---|
| 119 | inline ULONG NetworkToHostLong(ULONG netlong) | 
|---|
| 120 | { | 
|---|
| 121 | LIMITED_METHOD_CONTRACT; | 
|---|
| 122 |  | 
|---|
| 123 | if (BigEndian()) | 
|---|
| 124 | return netlong; | 
|---|
| 125 | else | 
|---|
| 126 | return  ( (netlong >> 24) & 0x000000FFL) | | 
|---|
| 127 | ( (netlong >>  8) & 0x0000FF00L) | | 
|---|
| 128 | ( (netlong <<  8) & 0x00FF0000L) | | 
|---|
| 129 | ( (netlong << 24) & 0xFF000000L); | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 | // NetworkToHostShort converts a 16-bit short to local host byte order | 
|---|
| 133 |  | 
|---|
| 134 | inline USHORT NetworkToHostShort(USHORT netshort) | 
|---|
| 135 | { | 
|---|
| 136 | LIMITED_METHOD_CONTRACT; | 
|---|
| 137 |  | 
|---|
| 138 | if (BigEndian()) | 
|---|
| 139 | return netshort; | 
|---|
| 140 | else | 
|---|
| 141 | return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00); | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | //============================================================================= | 
|---|
| 145 | // GuidFromName(GUID * pGuidResult, REFGUID refGuidNsid, | 
|---|
| 146 | //              const void * pvName, DWORD dwcbName); | 
|---|
| 147 | //============================================================================= | 
|---|
| 148 |  | 
|---|
| 149 | void GuidFromName | 
|---|
| 150 | ( | 
|---|
| 151 | GUID *  pGuidResult,        // resulting GUID | 
|---|
| 152 | REFGUID refGuidNsid,        // Name Space GUID, so identical names from | 
|---|
| 153 | // different name spaces generate different GUIDs | 
|---|
| 154 | const void * pvName,        // the name from which to generate a GUID | 
|---|
| 155 | DWORD dwcbName              // name length in bytes | 
|---|
| 156 | ) | 
|---|
| 157 | { | 
|---|
| 158 | STATIC_CONTRACT_NOTHROW; | 
|---|
| 159 | STATIC_CONTRACT_GC_NOTRIGGER; | 
|---|
| 160 |  | 
|---|
| 161 | MD5         md5;            // Cryptographic hash class instance | 
|---|
| 162 | MD5HASHDATA md5HashData;    // 128-bit hash result | 
|---|
| 163 | GUID        guidNsid;       // context NameSpace GUID in network byte order | 
|---|
| 164 |  | 
|---|
| 165 | GUID        guidTemp; | 
|---|
| 166 |  | 
|---|
| 167 | // put name space ID in network byte order so it hashes the same | 
|---|
| 168 | // no matter what endian machine we're on | 
|---|
| 169 | guidNsid = refGuidNsid; | 
|---|
| 170 |  | 
|---|
| 171 | // The sample code in the IETF draft document discards the result of | 
|---|
| 172 | // htonl and htons.  I've implemented what I think is meant and I've | 
|---|
| 173 | // sent a note to the author asking for confirmation that this is | 
|---|
| 174 | // his intent. | 
|---|
| 175 | if (!BigEndian())   // evaluated at compile time in retail builds | 
|---|
| 176 | { | 
|---|
| 177 | guidNsid.Data1 = HostToNetworkLong (guidNsid.Data1); | 
|---|
| 178 | guidNsid.Data2 = HostToNetworkShort(guidNsid.Data2); | 
|---|
| 179 | guidNsid.Data3 = HostToNetworkShort(guidNsid.Data3); | 
|---|
| 180 | } | 
|---|
| 181 |  | 
|---|
| 182 | md5.Init(); | 
|---|
| 183 | md5.HashMore(&guidNsid, sizeof(GUID)); | 
|---|
| 184 | md5.HashMore(pvName, dwcbName); | 
|---|
| 185 | md5.GetHashValue(&md5HashData); | 
|---|
| 186 |  | 
|---|
| 187 | // the hash is in network byte order at this point | 
|---|
| 188 | memcpy(&guidTemp, &md5HashData, sizeof(GUID)); | 
|---|
| 189 |  | 
|---|
| 190 | // Remainder adapted from function "format_uuid_v3" in IETF draft document | 
|---|
| 191 | // Construct a version 3 uuid with the pseudo-random number plus a few constants. | 
|---|
| 192 | // convert GUID from network order to local byte order | 
|---|
| 193 | if (!BigEndian())   // evaluated at compile time in retail builds | 
|---|
| 194 | { | 
|---|
| 195 | guidTemp.Data1 = NetworkToHostLong (guidTemp.Data1); | 
|---|
| 196 | guidTemp.Data2 = NetworkToHostShort(guidTemp.Data2); | 
|---|
| 197 | guidTemp.Data3 = NetworkToHostShort(guidTemp.Data3); | 
|---|
| 198 | } | 
|---|
| 199 |  | 
|---|
| 200 | // set version number | 
|---|
| 201 | guidTemp.Data3 &= 0x0FFF;   // clear version number nibble | 
|---|
| 202 | guidTemp.Data3 |= (3 << 12);// set version 3 = name-based | 
|---|
| 203 |  | 
|---|
| 204 | // set variant field | 
|---|
| 205 | guidTemp.Data4[0] &= 0x3F;  // clear variant bits | 
|---|
| 206 | guidTemp.Data4[0] |= 0x80;  // set variant = 100b | 
|---|
| 207 |  | 
|---|
| 208 | // If two GuidFromName calls were made from different threads with the same parameters, | 
|---|
| 209 | // we may get incorrect result even though the expected result is the same, because | 
|---|
| 210 | // GuidFromName is operating on the same pGuidResult buffer. | 
|---|
| 211 | // Fix this problem by using a temp GUID buffer and then copy to the pGuidResult buffer. | 
|---|
| 212 | memcpy(pGuidResult, &guidTemp, sizeof(GUID)); | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 |  | 
|---|
| 216 | // This guid is used for calling GuidFromName function as COM+ runtime uniqualifier | 
|---|
| 217 | // | 
|---|
| 218 | // {69F9CBC9-DA05-11d1-9408-0000F8083460} | 
|---|
| 219 | static const GUID COMPLUS_RUNTIME_GUID = {0x69f9cbc9, 0xda05, 0x11d1, | 
|---|
| 220 | {0x94, 0x8, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60}}; | 
|---|
| 221 |  | 
|---|
| 222 | void CorGuidFromNameW | 
|---|
| 223 | ( | 
|---|
| 224 | GUID *  pGuidResult,        // resulting GUID | 
|---|
| 225 | LPCWSTR wzName,             // the unicode name from which to generate a GUID | 
|---|
| 226 | SIZE_T  cchName             // name length in count of unicode character | 
|---|
| 227 | ) | 
|---|
| 228 | { | 
|---|
| 229 | WRAPPER_NO_CONTRACT; | 
|---|
| 230 |  | 
|---|
| 231 | GuidFromName( | 
|---|
| 232 | pGuidResult, | 
|---|
| 233 | COMPLUS_RUNTIME_GUID, | 
|---|
| 234 | wzName, | 
|---|
| 235 | (DWORD)((cchName == (SIZE_T) -1 ? (wcslen(wzName)+1) : cchName) * sizeof(WCHAR))); | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|