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
9Algorithm from Internet Draft document "UUIDs and GUIDs"
10By Paul J. Leach and Rich Sals, February 4, 1998.
11
12This function has been adapted from the routines in the document
13 uuid_create_from_name and format_uuid_v3
14
15Changes from documented routines:
161. 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
242. Use a c++ implementation of the md5 cryptographic hash function.
25
263. Implemented the htonl, htons, ntohl, ntohs socket routines as inlines.
27
284. Renamed variables and types to suit my biases.
29
30
31Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
32Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
33Digital Equipment Corporation, Maynard, Mass.
34To anyone who acknowledges that this file is provided "AS IS"
35without any express or implied warranty: permission to use, copy,
36modify, and distribute this file for any purpose is hereby
37granted without fee, provided that the above copyright notices and
38this notice appears in all source code copies, and that none of
39the names of Open Software Foundation, Inc., Hewlett-Packard
40Company, or Digital Equipment Corporation be used in advertising
41or publicity pertaining to distribution of the software without
42specific, written prior permission. Neither Open Software
43Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment
44Corporation makes any representations about the suitability of
45this software for any purpose.
46
47
48Copyright(C) The Internet Society 1997. All Rights Reserved.
49
50This document and translations of it may be copied and furnished to others,
51and derivative works that comment on or otherwise explain it or assist in
52its implementation may be prepared, copied, published and distributed, in
53whole or in part, without restriction of any kind, provided that the above
54copyright notice and this paragraph are included on all such copies and
55derivative works.However, this document itself may not be modified in any
56way, such as by removing the copyright notice or references to the Internet
57Society or other Internet organizations, except as needed for the purpose of
58developing Internet standards in which case the procedures for copyrights
59defined in the Internet Standards process must be followed, or as required
60to translate it into languages other than English.
61
62The limited permissions granted above are perpetual and will not be revoked
63by the Internet Society or its successors or assigns.
64
65This document and the information contained herein is provided on an "AS IS"
66basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE
67DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
68ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY
69RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
70PARTICULAR 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
92inline 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
107inline 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
119inline 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
134inline 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
149void 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}
219static const GUID COMPLUS_RUNTIME_GUID = {0x69f9cbc9, 0xda05, 0x11d1,
220 {0x94, 0x8, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60}};
221
222void 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