| 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 | |