| 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 | // NamespaceUtil.cpp | 
| 6 | // | 
| 7 |  | 
| 8 | // | 
| 9 | // Helpers for converting namespace separators. | 
| 10 | // | 
| 11 | //***************************************************************************** | 
| 12 | #include "stdafx.h"  | 
| 13 | #include "corhdr.h" | 
| 14 | #include "corhlpr.h" | 
| 15 | #include "sstring.h" | 
| 16 | #include "utilcode.h" | 
| 17 |  | 
| 18 | #ifndef _ASSERTE | 
| 19 | #define _ASSERTE(foo) | 
| 20 | #endif | 
| 21 |  | 
| 22 | #include "nsutilpriv.h" | 
| 23 |  | 
| 24 |  | 
| 25 | //***************************************************************************** | 
| 26 | // Determine how many chars large a fully qualified name would be given the | 
| 27 | // two parts of the name.  The return value includes room for every character | 
| 28 | // in both names, as well as room for the separator and a final terminator. | 
| 29 | //***************************************************************************** | 
| 30 | int ns::GetFullLength(                  // Number of chars in full name. | 
| 31 |     const WCHAR *szNameSpace,           // Namspace for value. | 
| 32 |     const WCHAR *szName)                // Name of value. | 
| 33 | { | 
| 34 |     STATIC_CONTRACT_NOTHROW; | 
| 35 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 36 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 37 |  | 
| 38 |     int iLen = 1;                       // Null terminator. | 
| 39 |     if (szNameSpace) | 
| 40 |         iLen += (int)wcslen(szNameSpace); | 
| 41 |     if (szName) | 
| 42 |         iLen += (int)wcslen(szName); | 
| 43 |     if (szNameSpace && *szNameSpace && szName && *szName) | 
| 44 |         ++iLen; | 
| 45 |     return iLen; | 
| 46 | }   //int ns::GetFullLength() | 
| 47 |  | 
| 48 | int ns::GetFullLength(                  // Number of chars in full name. | 
| 49 |     LPCUTF8     szNameSpace,            // Namspace for value. | 
| 50 |     LPCUTF8     szName)                 // Name of value. | 
| 51 | { | 
| 52 |     STATIC_CONTRACT_NOTHROW; | 
| 53 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 54 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 55 |  | 
| 56 |  | 
| 57 |     int iLen = 1; | 
| 58 |     if (szNameSpace) | 
| 59 |         iLen += (int)strlen(szNameSpace); | 
| 60 |     if (szName) | 
| 61 |         iLen += (int)strlen(szName); | 
| 62 |     if (szNameSpace && *szNameSpace && szName && *szName) | 
| 63 |         ++iLen; | 
| 64 |     return iLen; | 
| 65 | }   //int ns::GetFullLength() | 
| 66 |  | 
| 67 |  | 
| 68 | //***************************************************************************** | 
| 69 | // Scan the string from the rear looking for the first valid separator.  If | 
| 70 | // found, return a pointer to it.  Else return null.  This code is smart enough | 
| 71 | // to skip over special sequences, such as: | 
| 72 | //      a.b..ctor | 
| 73 | //         ^ | 
| 74 | //         | | 
| 75 | // The ".ctor" is considered one token. | 
| 76 | //***************************************************************************** | 
| 77 | WCHAR *ns::FindSep(                     // Pointer to separator or null. | 
| 78 |     const WCHAR *szPath)                // The path to look in. | 
| 79 | { | 
| 80 |     STATIC_CONTRACT_NOTHROW; | 
| 81 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 82 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 83 |  | 
| 84 |     _ASSERTE(szPath); | 
| 85 |     WCHAR *ptr = (WCHAR*)wcsrchr(szPath, NAMESPACE_SEPARATOR_WCHAR); | 
| 86 |     if((ptr == NULL) || (ptr == szPath)) return NULL; | 
| 87 |     if(*(ptr - 1) == NAMESPACE_SEPARATOR_WCHAR) // here ptr is at least szPath+1 | 
| 88 |         --ptr; | 
| 89 |     return ptr; | 
| 90 | }   //WCHAR *ns::FindSep() | 
| 91 |  | 
| 92 | //<TODO>@todo: this isn't dbcs safe if this were ansi, but this is utf8.  Still an issue?</TODO> | 
| 93 | LPUTF8 ns::FindSep(                     // Pointer to separator or null. | 
| 94 |     LPCUTF8     szPath)                 // The path to look in. | 
| 95 | { | 
| 96 |     STATIC_CONTRACT_NOTHROW; | 
| 97 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 98 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 99 |     STATIC_CONTRACT_SUPPORTS_DAC; | 
| 100 |  | 
| 101 |     _ASSERTE(szPath); | 
| 102 |     LPUTF8 ptr = const_cast<LPUTF8>(strrchr(szPath, NAMESPACE_SEPARATOR_CHAR)); | 
| 103 |     if((ptr == NULL) || (ptr == szPath)) return NULL; | 
| 104 |     if(*(ptr - 1) == NAMESPACE_SEPARATOR_CHAR) // here ptr is at least szPath+1 | 
| 105 |         --ptr; | 
| 106 |     return ptr; | 
| 107 | }   //LPUTF8 ns::FindSep() | 
| 108 |  | 
| 109 |  | 
| 110 |  | 
| 111 | //***************************************************************************** | 
| 112 | // Take a path and find the last separator (nsFindSep), and then replace the | 
| 113 | // separator with a '\0' and return a pointer to the name.  So for example: | 
| 114 | //      a.b.c | 
| 115 | // becomes two strings "a.b" and "c" and the return value points to "c". | 
| 116 | //***************************************************************************** | 
| 117 | WCHAR *ns::SplitInline(                 // Pointer to name portion. | 
| 118 |     __inout __inout_z WCHAR       *szPath)           // The path to split. | 
| 119 | { | 
| 120 |     STATIC_CONTRACT_NOTHROW; | 
| 121 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 122 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 123 |  | 
| 124 |     WCHAR *ptr = ns::FindSep(szPath); | 
| 125 |     if (ptr) | 
| 126 |     { | 
| 127 |         *ptr = 0; | 
| 128 |         ++ptr; | 
| 129 |     } | 
| 130 |     return ptr; | 
| 131 | }   // WCHAR *ns::SplitInline() | 
| 132 |  | 
| 133 | LPUTF8 ns::SplitInline(                 // Pointer to name portion. | 
| 134 |     __inout __inout_z LPUTF8  szPath)                 // The path to split. | 
| 135 | { | 
| 136 |     STATIC_CONTRACT_NOTHROW; | 
| 137 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 138 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 139 |  | 
| 140 |     LPUTF8 ptr = ns::FindSep(szPath); | 
| 141 |     if (ptr) | 
| 142 |     { | 
| 143 |         *ptr = 0; | 
| 144 |         ++ptr; | 
| 145 |     } | 
| 146 |     return ptr; | 
| 147 | }   // LPUTF8 ns::SplitInline() | 
| 148 |  | 
| 149 | void ns::SplitInline( | 
| 150 |     __inout __inout_z LPWSTR  szPath,                 // Path to split. | 
| 151 |     LPCWSTR     &szNameSpace,           // Return pointer to namespace. | 
| 152 |     LPCWSTR     &szName)                // Return pointer to name. | 
| 153 | { | 
| 154 |     STATIC_CONTRACT_NOTHROW; | 
| 155 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 156 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 157 |  | 
| 158 |     WCHAR *ptr = SplitInline(szPath); | 
| 159 |     if (ptr) | 
| 160 |     { | 
| 161 |         szNameSpace = szPath; | 
| 162 |         szName = ptr; | 
| 163 |     } | 
| 164 |     else | 
| 165 |     { | 
| 166 |         szNameSpace = 0; | 
| 167 |         szName = szPath; | 
| 168 |     } | 
| 169 | }   // void ns::SplitInline() | 
| 170 |  | 
| 171 | void ns::SplitInline( | 
| 172 |     __inout __inout_z LPUTF8  szPath,                 // Path to split. | 
| 173 |     LPCUTF8     &szNameSpace,           // Return pointer to namespace. | 
| 174 |     LPCUTF8     &szName)                // Return pointer to name. | 
| 175 | { | 
| 176 |     STATIC_CONTRACT_NOTHROW; | 
| 177 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 178 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 179 |  | 
| 180 |     LPUTF8 ptr = SplitInline(szPath); | 
| 181 |     if (ptr) | 
| 182 |     { | 
| 183 |         szNameSpace = szPath; | 
| 184 |         szName = ptr; | 
| 185 |     } | 
| 186 |     else | 
| 187 |     { | 
| 188 |         szNameSpace = 0; | 
| 189 |         szName = szPath; | 
| 190 |     } | 
| 191 | }   // void ns::SplitInline() | 
| 192 |  | 
| 193 |  | 
| 194 | //***************************************************************************** | 
| 195 | // Split the last parsable element from the end of the string as the name, | 
| 196 | // the first part as the namespace. | 
| 197 | //***************************************************************************** | 
| 198 | int ns::SplitPath(                      // true ok, false trunction. | 
| 199 |     const WCHAR *szPath,                // Path to split. | 
| 200 |     __out_ecount(cchNameSpace) WCHAR *szNameSpace,           // Output for namespace value. | 
| 201 |     int         cchNameSpace,           // Max chars for output. | 
| 202 |     __out_ecount(cchName)      WCHAR *szName,                // Output for name. | 
| 203 |     int         cchName)                // Max chars for output. | 
| 204 | { | 
| 205 |     STATIC_CONTRACT_NOTHROW; | 
| 206 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 207 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 208 |  | 
| 209 |     const WCHAR *ptr = ns::FindSep(szPath); | 
| 210 |     size_t iLen = (ptr) ? ptr - szPath : 0; | 
| 211 |     size_t iCopyMax; | 
| 212 |     int brtn = true; | 
| 213 |     if (szNameSpace && cchNameSpace) | 
| 214 |     { | 
| 215 |         _ASSERTE(cchNameSpace > 1);     | 
| 216 |         iCopyMax = cchNameSpace - 1; | 
| 217 |         iCopyMax = min(iCopyMax, iLen); | 
| 218 |         wcsncpy_s(szNameSpace, cchNameSpace, szPath, iCopyMax); | 
| 219 |         szNameSpace[iCopyMax] = 0; | 
| 220 |          | 
| 221 |         if (iLen >= (size_t)cchNameSpace) | 
| 222 |             brtn = false; | 
| 223 |     } | 
| 224 |  | 
| 225 |     if (szName && cchName) | 
| 226 |     { | 
| 227 |         _ASSERTE(cchName > 1);     | 
| 228 |         iCopyMax = cchName - 1; | 
| 229 |         if (ptr) | 
| 230 |             ++ptr; | 
| 231 |         else | 
| 232 |             ptr = szPath; | 
| 233 |         iLen = (int)wcslen(ptr); | 
| 234 |         iCopyMax = min(iCopyMax, iLen); | 
| 235 |         wcsncpy_s(szName, cchName, ptr, iCopyMax); | 
| 236 |         szName[iCopyMax] = 0; | 
| 237 |      | 
| 238 |         if (iLen >= (size_t)cchName) | 
| 239 |             brtn = false; | 
| 240 |     } | 
| 241 |     return brtn; | 
| 242 | }   // int ns::SplitPath() | 
| 243 |  | 
| 244 |  | 
| 245 | int ns::SplitPath(                      // true ok, false trunction. | 
| 246 |     LPCUTF8     szPath,                 // Path to split. | 
| 247 |     __out_ecount_opt (cchNameSpace) LPUTF8      szNameSpace,            // Output for namespace value. | 
| 248 |     int         cchNameSpace,           // Max chars for output. | 
| 249 |     __out_ecount_opt (cchName) LPUTF8      szName,                 // Output for name. | 
| 250 |     int         cchName)                // Max chars for output. | 
| 251 | { | 
| 252 |     STATIC_CONTRACT_NOTHROW; | 
| 253 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 254 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 255 |  | 
| 256 |     LPCUTF8 ptr = ns::FindSep(szPath); | 
| 257 |     size_t iLen = (ptr) ? ptr - szPath : 0; | 
| 258 |     size_t iCopyMax; | 
| 259 |     int brtn = true; | 
| 260 |     if (szNameSpace && cchNameSpace) | 
| 261 |     { | 
| 262 |         _ASSERTE(cchNameSpace > 1);     | 
| 263 |         iCopyMax = cchNameSpace-1; | 
| 264 |         iCopyMax = min(iCopyMax, iLen); | 
| 265 |         strncpy_s(szNameSpace, cchNameSpace, szPath, iCopyMax); | 
| 266 |         szNameSpace[iCopyMax] = 0; | 
| 267 |          | 
| 268 |         if (iLen >= (size_t)cchNameSpace) | 
| 269 |             brtn = false; | 
| 270 |     } | 
| 271 |  | 
| 272 |     if (szName && cchName) | 
| 273 |     { | 
| 274 |         _ASSERTE(cchName > 1);     | 
| 275 |         iCopyMax = cchName-1; | 
| 276 |         if (ptr) | 
| 277 |             ++ptr; | 
| 278 |         else | 
| 279 |             ptr = szPath; | 
| 280 |         iLen = (int)strlen(ptr); | 
| 281 |         iCopyMax = min(iCopyMax, iLen); | 
| 282 |         strncpy_s(szName, cchName, ptr, iCopyMax); | 
| 283 |         szName[iCopyMax] = 0; | 
| 284 |      | 
| 285 |         if (iLen >= (size_t)cchName) | 
| 286 |             brtn = false; | 
| 287 |     } | 
| 288 |     return brtn; | 
| 289 | }   // int ns::SplitPath() | 
| 290 |  | 
| 291 |  | 
| 292 | //***************************************************************************** | 
| 293 | // Take two values and put them together in a fully qualified path using the | 
| 294 | // correct separator. | 
| 295 | //***************************************************************************** | 
| 296 | int ns::MakePath(                       // true ok, false truncation. | 
| 297 |     __out_ecount(cchChars) WCHAR       *szOut,                 // output path for name. | 
| 298 |     int         cchChars,               // max chars for output path. | 
| 299 |     const WCHAR *szNameSpace,           // Namespace. | 
| 300 |     const WCHAR *szName)                // Name. | 
| 301 | { | 
| 302 |     STATIC_CONTRACT_NOTHROW; | 
| 303 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 304 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 305 |  | 
| 306 |     if (cchChars < 1) | 
| 307 |         return false; | 
| 308 |  | 
| 309 |     if (szOut) | 
| 310 |         *szOut = 0; | 
| 311 |     else | 
| 312 |         return false; | 
| 313 |          | 
| 314 |     if (szNameSpace && *szNameSpace != W('\0')) | 
| 315 |     { | 
| 316 |         if (wcsncpy_s(szOut, cchChars, szNameSpace, _TRUNCATE) == STRUNCATE) | 
| 317 |             return false; | 
| 318 |  | 
| 319 |         // Add namespace separator if a non-empty name was supplied | 
| 320 |         if (szName && *szName != W('\0')) | 
| 321 |         { | 
| 322 |             if (wcsncat_s(szOut, cchChars, NAMESPACE_SEPARATOR_WSTR, _TRUNCATE) == STRUNCATE) | 
| 323 |             { | 
| 324 |                 return false; | 
| 325 |             } | 
| 326 |         } | 
| 327 |     } | 
| 328 |      | 
| 329 |     if (szName && *szName) | 
| 330 |     { | 
| 331 |         if (wcsncat_s(szOut, cchChars, szName, _TRUNCATE) == STRUNCATE) | 
| 332 |             return false; | 
| 333 |     } | 
| 334 |      | 
| 335 |     return true; | 
| 336 | }   // int ns::MakePath() | 
| 337 |  | 
| 338 | int ns::MakePath(                       // true ok, false truncation. | 
| 339 |     __out_ecount(cchChars) LPUTF8      szOut,                  // output path for name. | 
| 340 |     int         cchChars,               // max chars for output path. | 
| 341 |     LPCUTF8     szNameSpace,            // Namespace. | 
| 342 |     LPCUTF8     szName)                 // Name. | 
| 343 | { | 
| 344 |     STATIC_CONTRACT_NOTHROW; | 
| 345 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 346 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 347 |  | 
| 348 |     if (cchChars < 1) | 
| 349 |         return false; | 
| 350 |  | 
| 351 |     if (szOut) | 
| 352 |         *szOut = 0; | 
| 353 |     else | 
| 354 |         return false; | 
| 355 |          | 
| 356 |     if (szNameSpace && *szNameSpace != W('\0')) | 
| 357 |     { | 
| 358 |         if (strncpy_s(szOut, cchChars, szNameSpace, _TRUNCATE) == STRUNCATE) | 
| 359 |             return false; | 
| 360 |  | 
| 361 |         // Add namespace separator if a non-empty name was supplied | 
| 362 |         if (szName && *szName != W('\0')) | 
| 363 |         { | 
| 364 |             if (strncat_s(szOut, cchChars, NAMESPACE_SEPARATOR_STR, _TRUNCATE) == STRUNCATE) | 
| 365 |             { | 
| 366 |                 return false; | 
| 367 |             } | 
| 368 |         } | 
| 369 |     } | 
| 370 |      | 
| 371 |     if (szName && *szName) | 
| 372 |     { | 
| 373 |         if (strncat_s(szOut, cchChars, szName, _TRUNCATE) == STRUNCATE) | 
| 374 |             return false; | 
| 375 |     } | 
| 376 |      | 
| 377 |     return true; | 
| 378 |  | 
| 379 | }   // int ns::MakePath() | 
| 380 |  | 
| 381 | int ns::MakePath(                       // true ok, false truncation. | 
| 382 |     __out_ecount(cchChars) WCHAR       *szOut,                 // output path for name. | 
| 383 |     int         cchChars,               // max chars for output path. | 
| 384 |     LPCUTF8     szNamespace,            // Namespace. | 
| 385 |     LPCUTF8     szName)                 // Name. | 
| 386 | { | 
| 387 |     STATIC_CONTRACT_NOTHROW; | 
| 388 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 389 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 390 |  | 
| 391 |     if (cchChars < 1) | 
| 392 |         return false; | 
| 393 |  | 
| 394 |     if (szOut) | 
| 395 |         *szOut = 0; | 
| 396 |     else | 
| 397 |         return false; | 
| 398 |      | 
| 399 |     if (szNamespace != NULL && *szNamespace != '\0') | 
| 400 |     { | 
| 401 |         if (cchChars < 2) | 
| 402 |             return false; | 
| 403 |  | 
| 404 |         int count; | 
| 405 |  | 
| 406 |         // We use cBuffer - 2 to account for the '.' and at least a 1 character name below. | 
| 407 |         count = WszMultiByteToWideChar(CP_UTF8, 0, szNamespace, -1, szOut, cchChars-2); | 
| 408 |         if (count == 0) | 
| 409 |             return false; // Supply a bigger buffer! | 
| 410 |  | 
| 411 |         // buffer access is bounded: WszMultiByteToWideChar returns 0 if access doesn't fit in range | 
| 412 | #ifdef _PREFAST_ | 
| 413 |         #pragma warning( suppress: 26015 )  | 
| 414 | #endif   | 
| 415 |         szOut[count-1] = NAMESPACE_SEPARATOR_WCHAR; | 
| 416 |         szOut += count; | 
| 417 |         cchChars -= count; | 
| 418 |     } | 
| 419 |  | 
| 420 |     if (((cchChars == 0) && (szName != NULL) && (*szName != '\0')) ||  | 
| 421 |         (WszMultiByteToWideChar(CP_UTF8, 0, szName, -1, szOut, cchChars) == 0)) | 
| 422 |         return false; // supply a bigger buffer! | 
| 423 |     return true; | 
| 424 | }   // int ns::MakePath() | 
| 425 |  | 
| 426 | int ns::MakePath(                       // true ok, false out of memory | 
| 427 |     CQuickBytes &qb,                    // Where to put results. | 
| 428 |     LPCUTF8     szNameSpace,            // Namespace for name. | 
| 429 |     LPCUTF8     szName)                 // Final part of name. | 
| 430 | { | 
| 431 |     STATIC_CONTRACT_NOTHROW; | 
| 432 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 433 |     STATIC_CONTRACT_FAULT; | 
| 434 |  | 
| 435 |     int iLen = 2; | 
| 436 |     if (szNameSpace) | 
| 437 |         iLen += (int)strlen(szNameSpace); | 
| 438 |     if (szName) | 
| 439 |         iLen += (int)strlen(szName); | 
| 440 |     LPUTF8 szOut = (LPUTF8) qb.AllocNoThrow(iLen); | 
| 441 |     if (!szOut) | 
| 442 |         return false; | 
| 443 |     return ns::MakePath(szOut, iLen, szNameSpace, szName); | 
| 444 | }   // int ns::MakePath() | 
| 445 |  | 
| 446 | int ns::MakePath(                       // true ok, false out of memory | 
| 447 |     CQuickArray<WCHAR> &qa,             // Where to put results. | 
| 448 |     LPCUTF8            szNameSpace,     // Namespace for name. | 
| 449 |     LPCUTF8            szName)          // Final part of name. | 
| 450 | { | 
| 451 |     STATIC_CONTRACT_NOTHROW; | 
| 452 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 453 |     STATIC_CONTRACT_FAULT; | 
| 454 |  | 
| 455 |     int iLen = 2; | 
| 456 |     if (szNameSpace) | 
| 457 |         iLen += (int)strlen(szNameSpace); | 
| 458 |     if (szName) | 
| 459 |         iLen += (int)strlen(szName); | 
| 460 |     WCHAR *szOut = (WCHAR *) qa.AllocNoThrow(iLen); | 
| 461 |     if (!szOut) | 
| 462 |         return false; | 
| 463 |     return ns::MakePath(szOut, iLen, szNameSpace, szName); | 
| 464 | }   // int ns::MakePath() | 
| 465 |  | 
| 466 | int ns::MakePath(                       // true ok, false out of memory | 
| 467 |     CQuickBytes &qb,                    // Where to put results. | 
| 468 |     const WCHAR *szNameSpace,           // Namespace for name. | 
| 469 |     const WCHAR *szName)                // Final part of name. | 
| 470 | { | 
| 471 |     STATIC_CONTRACT_NOTHROW; | 
| 472 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 473 |     STATIC_CONTRACT_FAULT; | 
| 474 |  | 
| 475 |     int iLen = 2; | 
| 476 |     if (szNameSpace) | 
| 477 |         iLen += (int)wcslen(szNameSpace); | 
| 478 |     if (szName) | 
| 479 |         iLen += (int)wcslen(szName); | 
| 480 |     WCHAR *szOut = (WCHAR *) qb.AllocNoThrow(iLen * sizeof(WCHAR)); | 
| 481 |     if (!szOut) | 
| 482 |         return false; | 
| 483 |     return ns::MakePath(szOut, iLen, szNameSpace, szName); | 
| 484 | }   // int ns::MakePath() | 
| 485 |  | 
| 486 | void ns::MakePath(                      // throws on out of memory | 
| 487 |     SString       &ssBuf,               // Where to put results. | 
| 488 |     const SString &ssNameSpace,         // Namespace for name. | 
| 489 |     const SString &ssName)              // Final part of name. | 
| 490 | { | 
| 491 |     STATIC_CONTRACT_THROWS; | 
| 492 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 493 |     STATIC_CONTRACT_FAULT; | 
| 494 |  | 
| 495 |     ssBuf.Clear(); | 
| 496 |  | 
| 497 |     if (!ssNameSpace.IsEmpty()) | 
| 498 |     { | 
| 499 |         if (ssName.IsEmpty()) | 
| 500 |         { | 
| 501 |             ssBuf.Set(ssNameSpace); | 
| 502 |         } | 
| 503 |         else | 
| 504 |         { | 
| 505 |             SString s(SString::Literal, NAMESPACE_SEPARATOR_WSTR); | 
| 506 |             ssBuf.Set(ssNameSpace, s); | 
| 507 |         } | 
| 508 |     } | 
| 509 |  | 
| 510 |     if (!ssName.IsEmpty()) | 
| 511 |     { | 
| 512 |         ssBuf.Append(ssName); | 
| 513 |     } | 
| 514 | } | 
| 515 |  | 
| 516 | bool ns::MakeAssemblyQualifiedName(                                        // true ok, false truncation | 
| 517 |                                    __out_ecount(dwBuffer) WCHAR* pBuffer,  // Buffer to recieve the results | 
| 518 |                                    int    dwBuffer,                        // Number of characters total in buffer | 
| 519 |                                    const WCHAR *szTypeName,                // Namespace for name. | 
| 520 |                                    int   dwTypeName,                       // Number of characters (not including null) | 
| 521 |                                    const WCHAR *szAssemblyName,            // Final part of name. | 
| 522 |                                    int   dwAssemblyName)                   // Number of characters (not including null) | 
| 523 | { | 
| 524 |     STATIC_CONTRACT_NOTHROW; | 
| 525 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 526 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 527 |  | 
| 528 |     if (dwBuffer < 2) | 
| 529 |         return false; | 
| 530 |  | 
| 531 |     int iCopyMax = 0; | 
| 532 |     _ASSERTE(pBuffer); | 
| 533 |     *pBuffer = NULL; | 
| 534 |      | 
| 535 |     if (szTypeName && *szTypeName != W('\0')) | 
| 536 |     { | 
| 537 |         _ASSERTE(dwTypeName > 0); | 
| 538 |         iCopyMax = min(dwBuffer-1, dwTypeName); | 
| 539 |         wcsncpy_s(pBuffer, dwBuffer, szTypeName, iCopyMax); | 
| 540 |         dwBuffer -= iCopyMax; | 
| 541 |     } | 
| 542 |      | 
| 543 |     if (szAssemblyName && *szAssemblyName != W('\0')) | 
| 544 |     { | 
| 545 |          | 
| 546 |         if(dwBuffer < ASSEMBLY_SEPARATOR_LEN)  | 
| 547 |             return false; | 
| 548 |  | 
| 549 |         for(DWORD i = 0; i < ASSEMBLY_SEPARATOR_LEN; i++) | 
| 550 |             pBuffer[iCopyMax+i] = ASSEMBLY_SEPARATOR_WSTR[i]; | 
| 551 |  | 
| 552 |         dwBuffer -= ASSEMBLY_SEPARATOR_LEN; | 
| 553 |         if(dwBuffer == 0)  | 
| 554 |             return false; | 
| 555 |  | 
| 556 |         int iCur = iCopyMax + ASSEMBLY_SEPARATOR_LEN; | 
| 557 |         _ASSERTE(dwAssemblyName > 0); | 
| 558 |         iCopyMax = min(dwBuffer-1, dwAssemblyName); | 
| 559 |         wcsncpy_s(pBuffer + iCur, dwBuffer, szAssemblyName, iCopyMax); | 
| 560 |         pBuffer[iCur + iCopyMax] = W('\0'); | 
| 561 |          | 
| 562 |         if (iCopyMax < dwAssemblyName) | 
| 563 |             return false; | 
| 564 |     } | 
| 565 |     else { | 
| 566 |         if(dwBuffer == 0) { | 
| 567 |             PREFIX_ASSUME(iCopyMax > 0); | 
| 568 |             pBuffer[iCopyMax-1] = W('\0'); | 
| 569 |             return false; | 
| 570 |         } | 
| 571 |         else | 
| 572 |             pBuffer[iCopyMax] = W('\0'); | 
| 573 |     } | 
| 574 |      | 
| 575 |     return true; | 
| 576 | }   // int ns::MakePath() | 
| 577 |  | 
| 578 | bool ns::MakeAssemblyQualifiedName(                                        // true ok, false out of memory | 
| 579 |                                    CQuickBytes &qb,                        // Where to put results. | 
| 580 |                                    const WCHAR *szTypeName,                // Namespace for name. | 
| 581 |                                    const WCHAR *szAssemblyName)            // Final part of name. | 
| 582 | { | 
| 583 |     STATIC_CONTRACT_NOTHROW; | 
| 584 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 585 |     STATIC_CONTRACT_FAULT; | 
| 586 |  | 
| 587 |     int iTypeName = 0; | 
| 588 |     int iAssemblyName = 0; | 
| 589 |     if (szTypeName) | 
| 590 |         iTypeName = (int)wcslen(szTypeName); | 
| 591 |     if (szAssemblyName) | 
| 592 |         iAssemblyName = (int)wcslen(szAssemblyName); | 
| 593 |  | 
| 594 |     int iLen = ASSEMBLY_SEPARATOR_LEN + iTypeName + iAssemblyName + 1; // Space for null terminator | 
| 595 |     WCHAR *szOut = (WCHAR *) qb.AllocNoThrow(iLen * sizeof(WCHAR)); | 
| 596 |     if (!szOut) | 
| 597 |         return false; | 
| 598 |  | 
| 599 |     bool ret; | 
| 600 |     ret = ns::MakeAssemblyQualifiedName(szOut, iLen, szTypeName, iTypeName, szAssemblyName, iAssemblyName); | 
| 601 |     _ASSERTE(ret); | 
| 602 |     return true; | 
| 603 | }    | 
| 604 |  | 
| 605 | int ns::MakeNestedTypeName(             // true ok, false out of memory | 
| 606 |     CQuickBytes &qb,                    // Where to put results. | 
| 607 |     LPCUTF8     szEnclosingName,        // Full name for enclosing type | 
| 608 |     LPCUTF8     szNestedName)           // Full name for nested type | 
| 609 | { | 
| 610 |     STATIC_CONTRACT_NOTHROW; | 
| 611 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 612 |     STATIC_CONTRACT_FAULT; | 
| 613 |  | 
| 614 |     _ASSERTE(szEnclosingName && szNestedName); | 
| 615 |     int iLen = 2; | 
| 616 |     iLen += (int)strlen(szEnclosingName); | 
| 617 |     iLen += (int)strlen(szNestedName); | 
| 618 |     LPUTF8 szOut = (LPUTF8) qb.AllocNoThrow(iLen); | 
| 619 |     if (!szOut) | 
| 620 |         return false; | 
| 621 |     return ns::MakeNestedTypeName(szOut, iLen, szEnclosingName, szNestedName); | 
| 622 | }   // int ns::MakeNestedTypeName() | 
| 623 |  | 
| 624 | int ns::MakeNestedTypeName(             // true ok, false truncation. | 
| 625 |     __out_ecount (cchChars) LPUTF8      szOut,                  // output path for name. | 
| 626 |     int         cchChars,               // max chars for output path. | 
| 627 |     LPCUTF8     szEnclosingName,        // Full name for enclosing type | 
| 628 |     LPCUTF8     szNestedName)           // Full name for nested type | 
| 629 | { | 
| 630 |     STATIC_CONTRACT_NOTHROW; | 
| 631 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 632 |     STATIC_CONTRACT_FORBID_FAULT; | 
| 633 |  | 
| 634 |     if (cchChars < 1) | 
| 635 |         return false; | 
| 636 |  | 
| 637 |     int iCopyMax = 0, iLen; | 
| 638 |     int brtn = true; | 
| 639 |     *szOut = 0; | 
| 640 |      | 
| 641 |     iLen = (int)strlen(szEnclosingName); | 
| 642 |     iCopyMax = min(cchChars-1, iLen); | 
| 643 |     strncpy_s(szOut, cchChars, szEnclosingName, iCopyMax); | 
| 644 |      | 
| 645 |     if (iLen >= cchChars) | 
| 646 |         brtn =  false; | 
| 647 |  | 
| 648 |     szOut[iCopyMax] = NESTED_SEPARATOR_CHAR; | 
| 649 |     int iCur = iCopyMax+1; // iCopyMax characters + nested_separator_char | 
| 650 |     cchChars -= iCur; | 
| 651 |     if(cchChars == 0)  | 
| 652 |         return false; | 
| 653 |  | 
| 654 |     iLen = (int)strlen(szNestedName); | 
| 655 |     iCopyMax = min(cchChars-1, iLen); | 
| 656 |     strncpy_s(&szOut[iCur], cchChars, szNestedName, iCopyMax); | 
| 657 |     szOut[iCur + iCopyMax] = 0; | 
| 658 |      | 
| 659 |     if (iLen >= cchChars) | 
| 660 |         brtn = false; | 
| 661 |      | 
| 662 |     return brtn; | 
| 663 | }   // int ns::MakeNestedTypeName() | 
| 664 |  | 
| 665 | void ns::MakeNestedTypeName(            // throws on out of memory | 
| 666 |     SString        &ssBuf,              // output path for name. | 
| 667 |     const SString  &ssEnclosingName,    // Full name for enclosing type | 
| 668 |     const SString  &ssNestedName)       // Full name for nested type | 
| 669 | { | 
| 670 |     STATIC_CONTRACT_THROWS; | 
| 671 |     STATIC_CONTRACT_GC_NOTRIGGER; | 
| 672 |  | 
| 673 |     ssBuf.Clear(); | 
| 674 |  | 
| 675 |     ssBuf.Append(ssEnclosingName); | 
| 676 |     ssBuf.Append(NESTED_SEPARATOR_WCHAR); | 
| 677 |     ssBuf.Append(ssNestedName); | 
| 678 | } | 
| 679 |  | 
| 680 |  |