Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

880 lines
18 KiB

  1. /*
  2. File GuidMap.c
  3. Defines interface to map a guid interface name to an unique descriptive
  4. name describing that interface and vice versa.
  5. Paul Mayfield, 8/25/97
  6. Copyright 1997, Microsoft Corporation.
  7. */
  8. #include <nt.h>
  9. #include <ntrtl.h>
  10. #include <nturtl.h>
  11. #include <windows.h>
  12. #include <winerror.h>
  13. #include <netcfgx.h>
  14. #include <netcon.h>
  15. #include "rtcfg.h"
  16. #include "guidmap.h"
  17. #include "enumlan.h"
  18. #include "hashtab.h"
  19. #define GUIDMAP_HASH_SIZE 101
  20. #define GUIDMAP_FUNCTION_MAPFRIENDLY 0x1
  21. #define GUIDMAP_FUNCTION_MAPGUID 0x2
  22. //
  23. // Structure defines the control block for a guid map
  24. //
  25. typedef struct _GUIDMAPCB
  26. {
  27. PWCHAR pszServer;
  28. BOOL bNt40;
  29. EL_ADAPTER_INFO * pNodes;
  30. DWORD dwNodeCount;
  31. HANDLE hNameHashTable;
  32. HANDLE hGuidHashTable;
  33. BOOL bLoaded;
  34. } GUIDMAPCB;
  35. DWORD
  36. GuidMapSeedHashTable (
  37. OUT HANDLE * phTable,
  38. IN HashTabHashFuncPtr pHashFunc,
  39. IN HashTabKeyCompFuncPtr pCompFunc,
  40. IN EL_ADAPTER_INFO * pNodes,
  41. IN DWORD dwCount,
  42. IN DWORD dwOffset);
  43. ULONG
  44. GuidMapHashGuid (
  45. IN HANDLE hGuid);
  46. ULONG
  47. GuidMapHashName (
  48. IN HANDLE hName);
  49. int
  50. GuidMapCompGuids (
  51. IN HANDLE hGuid,
  52. IN HANDLE hNameMapNode);
  53. int
  54. GuidMapCompNames (
  55. IN HANDLE hName,
  56. IN HANDLE hNameMapNode);
  57. //
  58. // Initialize the guid map for the given server
  59. //
  60. DWORD
  61. GuidMapInit (
  62. IN PWCHAR pszServer,
  63. OUT HANDLE * phGuidMap )
  64. {
  65. GUIDMAPCB * pMapCb;
  66. // Validate params
  67. if (! phGuidMap)
  68. {
  69. return ERROR_INVALID_PARAMETER;
  70. }
  71. // Allocate the control block
  72. pMapCb = Malloc (sizeof (GUIDMAPCB));
  73. if (!pMapCb)
  74. {
  75. return ERROR_NOT_ENOUGH_MEMORY;
  76. }
  77. // Initialize
  78. RtlZeroMemory (pMapCb, sizeof (GUIDMAPCB));
  79. pMapCb->pszServer = pszServer;
  80. *phGuidMap = (HANDLE)pMapCb;
  81. return NO_ERROR;
  82. }
  83. //
  84. // Loads and prepares the guid map so that it can
  85. // perform the given map function (a GUIDMAP_FUNCTION_XXX value).
  86. //
  87. DWORD GuidMapLoad (
  88. IN GUIDMAPCB * pMapCb,
  89. IN DWORD dwFunction)
  90. {
  91. DWORD dwErr;
  92. // We've done all the work we need to if we aren't looking
  93. // at an nt5 machine
  94. if (pMapCb->bNt40)
  95. {
  96. return NO_ERROR;
  97. }
  98. // Load the guid map
  99. if (! pMapCb->bLoaded)
  100. {
  101. dwErr = ElEnumLanAdapters (
  102. pMapCb->pszServer,
  103. &(pMapCb->pNodes),
  104. &(pMapCb->dwNodeCount),
  105. &(pMapCb->bNt40) );
  106. if (dwErr != NO_ERROR)
  107. {
  108. return dwErr;
  109. }
  110. pMapCb->bLoaded = TRUE;
  111. }
  112. // Seed the appropriate mapping hash table as needed
  113. if ((dwFunction == GUIDMAP_FUNCTION_MAPFRIENDLY) &&
  114. (pMapCb->hGuidHashTable == NULL))
  115. {
  116. GuidMapSeedHashTable (
  117. &(pMapCb->hGuidHashTable),
  118. GuidMapHashGuid,
  119. GuidMapCompGuids,
  120. pMapCb->pNodes,
  121. pMapCb->dwNodeCount,
  122. FIELD_OFFSET(EL_ADAPTER_INFO, guid));
  123. }
  124. else if ((dwFunction == GUIDMAP_FUNCTION_MAPGUID) &&
  125. (pMapCb->hNameHashTable == NULL))
  126. {
  127. GuidMapSeedHashTable (
  128. &(pMapCb->hNameHashTable),
  129. GuidMapHashName,
  130. GuidMapCompNames,
  131. pMapCb->pNodes,
  132. pMapCb->dwNodeCount,
  133. FIELD_OFFSET(EL_ADAPTER_INFO, pszName));
  134. }
  135. return NO_ERROR;
  136. }
  137. //
  138. // Cleans up resources obtained through GuidMapInit
  139. //
  140. DWORD
  141. GuidMapCleanup (
  142. IN HANDLE hGuidMap,
  143. IN BOOL bFree
  144. )
  145. {
  146. GUIDMAPCB * pMap = (GUIDMAPCB*)hGuidMap;
  147. if (!pMap)
  148. {
  149. return ERROR_INVALID_HANDLE;
  150. }
  151. if (pMap->pNodes)
  152. {
  153. ElCleanup (pMap->pNodes, pMap->dwNodeCount);
  154. }
  155. if (pMap->hNameHashTable)
  156. {
  157. HashTabCleanup (pMap->hNameHashTable);
  158. }
  159. if (pMap->hGuidHashTable)
  160. {
  161. HashTabCleanup (pMap->hGuidHashTable);
  162. }
  163. RtlZeroMemory (pMap, sizeof(GUIDMAPCB));
  164. if(bFree)
  165. {
  166. Free (pMap);
  167. }
  168. return NO_ERROR;
  169. }
  170. //
  171. // Hash function for guids -- sum up the guid and mod
  172. //
  173. ULONG
  174. GuidMapHashGuid (
  175. HANDLE hGuid)
  176. {
  177. DWORD dwSum = 0, * pdwCur;
  178. DWORD_PTR dwEnd = (DWORD_PTR)hGuid + sizeof(GUID);
  179. for (pdwCur = (DWORD*)hGuid; (DWORD_PTR)pdwCur < dwEnd; pdwCur++)
  180. {
  181. dwSum += *pdwCur;
  182. }
  183. return dwSum % GUIDMAP_HASH_SIZE;
  184. }
  185. //
  186. // Hash function for names -- sum up the characters and mod
  187. //
  188. ULONG
  189. GuidMapHashName (
  190. HANDLE hName)
  191. {
  192. PWCHAR pszString = *((PWCHAR *)hName);
  193. DWORD dwSum = 0;
  194. while (pszString && *pszString)
  195. {
  196. dwSum += towlower(*pszString);
  197. pszString++;
  198. }
  199. return dwSum % GUIDMAP_HASH_SIZE;
  200. }
  201. //
  202. // Comparison function for guids to NAMEMAPNODES
  203. //
  204. int
  205. GuidMapCompGuids (
  206. IN HANDLE hGuid,
  207. IN HANDLE hNameMapNode)
  208. {
  209. return memcmp (
  210. (GUID*)hGuid,
  211. &(((EL_ADAPTER_INFO *)hNameMapNode)->guid),
  212. sizeof(GUID));
  213. }
  214. //
  215. // Comparison function for names to NAMEMAPNODES
  216. //
  217. int
  218. GuidMapCompNames (
  219. IN HANDLE hName,
  220. IN HANDLE hNameMapNode)
  221. {
  222. return lstrcmpi(
  223. *((PWCHAR*)hName),
  224. ((EL_ADAPTER_INFO *)hNameMapNode)->pszName);
  225. }
  226. //
  227. // Seeds the given hash table. Offset is the offset into the
  228. // namemapnode of the key for insertion.
  229. //
  230. DWORD
  231. GuidMapSeedHashTable (
  232. OUT HANDLE * phTable,
  233. IN HashTabHashFuncPtr pHashFunc,
  234. IN HashTabKeyCompFuncPtr pCompFunc,
  235. IN EL_ADAPTER_INFO * pNodes,
  236. IN DWORD dwCount,
  237. IN DWORD dwOffset)
  238. {
  239. DWORD dwErr, i, dwHashSize = GUIDMAP_HASH_SIZE;
  240. // Initialize the hash table
  241. dwErr = HashTabCreate (
  242. dwHashSize,
  243. pHashFunc,
  244. pCompFunc,
  245. NULL,
  246. NULL,
  247. NULL,
  248. phTable );
  249. if (dwErr != NO_ERROR)
  250. {
  251. return dwErr;
  252. }
  253. // Add all of the nodes to the hash table
  254. for (i = 0; i < dwCount; i++)
  255. {
  256. HashTabInsert (
  257. *phTable,
  258. (HANDLE)((DWORD_PTR)(&(pNodes[i])) + dwOffset),
  259. (HANDLE)(&(pNodes[i])) );
  260. }
  261. return NO_ERROR;
  262. }
  263. //
  264. // Gets the name and status of a given adapter
  265. //
  266. DWORD
  267. GuidMapLookupNameAndStatus(
  268. GUIDMAPCB* pMapCb,
  269. GUID* pGuid,
  270. PWCHAR* ppszName,
  271. DWORD* lpdwStatus)
  272. {
  273. EL_ADAPTER_INFO * pNode;
  274. DWORD dwErr;
  275. dwErr = HashTabFind (
  276. pMapCb->hGuidHashTable,
  277. (HANDLE)pGuid,
  278. (HANDLE*)&pNode );
  279. if (dwErr != NO_ERROR)
  280. {
  281. return dwErr;
  282. }
  283. *ppszName = pNode->pszName;
  284. *lpdwStatus = pNode->dwStatus;
  285. return NO_ERROR;
  286. }
  287. //
  288. // Looks up a name given a guid
  289. //
  290. DWORD
  291. GuidMapLookupName (
  292. GUIDMAPCB * pMapCb,
  293. GUID * pGuid,
  294. PWCHAR * ppszName)
  295. {
  296. DWORD dwStatus;
  297. return GuidMapLookupNameAndStatus(pMapCb, pGuid, ppszName, &dwStatus);
  298. }
  299. //
  300. // Looks up a guid given a name
  301. //
  302. DWORD
  303. GuidMapLookupGuid (
  304. IN GUIDMAPCB * pMapCb,
  305. IN PWCHAR pszName,
  306. GUID * pGuid)
  307. {
  308. EL_ADAPTER_INFO * pNode;
  309. DWORD dwErr;
  310. dwErr = HashTabFind (
  311. pMapCb->hNameHashTable,
  312. (HANDLE)&pszName,
  313. (HANDLE*)&pNode );
  314. if (dwErr != NO_ERROR)
  315. {
  316. return dwErr;
  317. }
  318. *pGuid = pNode->guid;
  319. return NO_ERROR;
  320. }
  321. //
  322. // Returns a pointer to the packet name portion of
  323. // the interface name if it exists.
  324. //
  325. PWCHAR
  326. GuidMapFindPacketName(
  327. IN PWCHAR pszName)
  328. {
  329. PWCHAR res;
  330. if ((res = wcsstr(pszName, L"SNAP")) != NULL)
  331. {
  332. return res;
  333. }
  334. if ((res = wcsstr(pszName, L"EthII")) != NULL)
  335. {
  336. return res;
  337. }
  338. if ((res = wcsstr(pszName, L"802.2")) != NULL)
  339. {
  340. return res;
  341. }
  342. if ((res = wcsstr(pszName, L"802.3")) != NULL)
  343. {
  344. return res;
  345. }
  346. return NULL;
  347. }
  348. //
  349. // Takes in a friendly interface name and removes it's
  350. // [xxxx] packet type appending.
  351. //
  352. DWORD
  353. GuidMapParseOutPacketName (
  354. IN PWCHAR pszName,
  355. OUT PWCHAR pszNameNoPacket,
  356. OUT PWCHAR pszPacketName)
  357. {
  358. PWCHAR pszPacket = GuidMapFindPacketName (pszName);
  359. int len;
  360. if (pszPacket)
  361. {
  362. pszPacket--;
  363. len = (int) ((((DWORD_PTR)pszPacket) -
  364. ((DWORD_PTR)pszName)) /
  365. sizeof (WCHAR));
  366. lstrcpynW (pszNameNoPacket, pszName, len);
  367. pszNameNoPacket[len] = 0;
  368. pszPacket++;
  369. pszPacket[wcslen(pszPacket) - 1] = (WCHAR)0;
  370. lstrcpyW (pszPacketName, pszPacket);
  371. }
  372. else
  373. {
  374. lstrcpyW (pszNameNoPacket, pszName);
  375. pszPacketName[0] = 0;
  376. }
  377. return NO_ERROR;
  378. }
  379. //
  380. // Generates the version of the interface as stored in the registry. This
  381. // is done by finding the packet type if any and appending it to the
  382. // guid name.
  383. //
  384. DWORD
  385. GuidMapFormatGuidName(
  386. OUT PWCHAR pszDest,
  387. IN DWORD dwBufferSize,
  388. IN PWCHAR pszGuidName,
  389. IN PWCHAR pszPacketType)
  390. {
  391. DWORD dwSize;
  392. // Upper case the guid name
  393. _wcsupr(pszGuidName);
  394. // Calculate the space required for storing pszGuidName, the opening and
  395. // closing braces, and the terminating NULL
  396. dwSize = (wcslen(pszGuidName) + 2 + 1)* sizeof (WCHAR);
  397. if ( pszPacketType[0] )
  398. {
  399. // add the space required to store the pszPacketType and "/"
  400. dwSize += (wcslen(pszPacketType) + 1) * sizeof (WCHAR);
  401. }
  402. if ( dwBufferSize < dwSize )
  403. {
  404. return ERROR_BUFFER_OVERFLOW;
  405. }
  406. // Generate the name
  407. if (pszPacketType[0])
  408. {
  409. wsprintfW(pszDest,L"{%s}/%s", pszGuidName, pszPacketType);
  410. }
  411. else
  412. {
  413. wsprintfW(pszDest,L"{%s}", pszGuidName);
  414. }
  415. return NO_ERROR;
  416. }
  417. //
  418. // Appends the packet type if any to the interface name.
  419. //
  420. DWORD
  421. GuidMapFormatFriendlyName (
  422. OUT PWCHAR pszDest,
  423. IN DWORD dwBufferSize,
  424. IN PWCHAR pszFriendlyName,
  425. IN PWCHAR pszGuidName)
  426. {
  427. PWCHAR pszType = NULL;
  428. DWORD dwSize;
  429. pszType = GuidMapFindPacketName(pszGuidName);
  430. // Calculate the space required for storing pszFriendlyName and the terminating NULL
  431. dwSize = (wcslen(pszFriendlyName) + 1)* sizeof (WCHAR);
  432. if ( pszType )
  433. {
  434. // add the space required to store the pszType, the blank space, and the
  435. // opening and closing square brackets
  436. dwSize += (wcslen(pszType) + 3) * sizeof (WCHAR);
  437. }
  438. if ( dwBufferSize < dwSize )
  439. {
  440. return ERROR_BUFFER_OVERFLOW;
  441. }
  442. if (pszType)
  443. {
  444. wsprintfW(pszDest,L"%s [%s]", pszFriendlyName, pszType);
  445. }
  446. else
  447. {
  448. wcscpy(pszDest, pszFriendlyName);
  449. }
  450. return NO_ERROR;
  451. }
  452. //
  453. // Parses out the guid portion of an interface name
  454. //
  455. DWORD
  456. GuidMapGetGuidString(
  457. IN PWCHAR pszName,
  458. OUT PWCHAR* ppszGuidString)
  459. {
  460. PWCHAR pszBegin = NULL, pszEnd = NULL;
  461. PWCHAR pszRet = NULL;
  462. int i, length;
  463. DWORD dwErr = NO_ERROR;
  464. do
  465. {
  466. // Validate parameters
  467. //
  468. if (!pszName || !ppszGuidString)
  469. {
  470. return ERROR_INVALID_PARAMETER;
  471. }
  472. // Find out if this is a guid string
  473. pszBegin = wcsstr(pszName, L"{");
  474. pszEnd = wcsstr(pszName, L"}");
  475. // If there is no guid portion, return success with a
  476. //null pszGuidString
  477. if ((pszBegin == NULL) || (pszEnd == NULL))
  478. {
  479. *ppszGuidString = NULL;
  480. break;
  481. }
  482. // Check the format of the return
  483. //
  484. if ((DWORD_PTR)pszBegin >= (DWORD_PTR)pszEnd)
  485. {
  486. dwErr = ERROR_CAN_NOT_COMPLETE;
  487. break;
  488. }
  489. // Allocate the return value
  490. //
  491. length = 41;
  492. pszRet = (PWCHAR) Malloc(length * sizeof(WCHAR));
  493. if (pszRet == NULL)
  494. {
  495. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  496. break;
  497. }
  498. i=0;
  499. pszBegin++;
  500. while ((pszBegin != pszEnd) && (i < length))
  501. {
  502. pszRet[i++]=*pszBegin;
  503. pszBegin++;
  504. }
  505. pszRet[i]=0;
  506. *ppszGuidString = pszRet;
  507. } while (FALSE);
  508. // Cleanup
  509. {
  510. if (dwErr != NO_ERROR)
  511. {
  512. if (pszRet)
  513. {
  514. Free(pszRet);
  515. }
  516. }
  517. }
  518. return dwErr;
  519. }
  520. //
  521. // Derive the friendly name from the guid name
  522. //
  523. DWORD
  524. GuidMapGetFriendlyName (
  525. IN SERVERCB *pserver,
  526. IN PWCHAR pszGuidName,
  527. IN DWORD dwBufferSize,
  528. OUT PWCHAR pszFriendlyName )
  529. {
  530. GUIDMAPCB * pMapCb = (GUIDMAPCB*)(pserver->hGuidMap);
  531. PWCHAR pszGuidString = NULL, pszNetmanName = NULL;
  532. DWORD dwErr = NO_ERROR;
  533. GUID Guid;
  534. // Sanity Check
  535. if (!pMapCb || !pszGuidName || !pszFriendlyName || !dwBufferSize)
  536. {
  537. return ERROR_INVALID_PARAMETER;
  538. }
  539. // Prepare the map for friendly name lookups
  540. dwErr = GuidMapLoad (pMapCb, GUIDMAP_FUNCTION_MAPFRIENDLY);
  541. if (dwErr != NO_ERROR)
  542. {
  543. return dwErr;
  544. }
  545. // Nt40 machines require no mapping
  546. if (pMapCb->bNt40)
  547. {
  548. return ERROR_NOT_FOUND;
  549. }
  550. do
  551. {
  552. // Get the guid string from the interface name
  553. dwErr = GuidMapGetGuidString(pszGuidName, &pszGuidString);
  554. if (dwErr != NO_ERROR)
  555. {
  556. break;
  557. }
  558. // If there is no guid, there is no mapping
  559. if (! pszGuidString)
  560. {
  561. dwErr = ERROR_NOT_FOUND;
  562. break;
  563. }
  564. // Convert the guid string
  565. if (UuidFromStringW (pszGuidString, &Guid)!= RPC_S_OK) {
  566. dwErr = ERROR_CAN_NOT_COMPLETE;
  567. break;
  568. }
  569. // Look up the descriptive name
  570. dwErr = GuidMapLookupName (pMapCb, &Guid, &pszNetmanName);
  571. if (dwErr != NO_ERROR)
  572. {
  573. break;
  574. }
  575. // If the registry is corrupt, it is possible for an
  576. // adapter with a null name to be mapped. Taking this
  577. // precaution will prevent an AV in this
  578. // case (shouldn't happen anyway)
  579. //
  580. if (pszNetmanName == NULL)
  581. {
  582. pszNetmanName = L"";
  583. }
  584. // Copy in the string
  585. dwErr = GuidMapFormatFriendlyName (
  586. pszFriendlyName,
  587. dwBufferSize,
  588. pszNetmanName,
  589. pszGuidName);
  590. if ( dwErr != NO_ERROR )
  591. {
  592. break;
  593. }
  594. } while (FALSE);
  595. // Cleanup
  596. {
  597. if (pszGuidString)
  598. {
  599. Free (pszGuidString);
  600. }
  601. }
  602. return dwErr;
  603. }
  604. //
  605. // Derive the guid name from the friendly name
  606. //
  607. DWORD
  608. GuidMapGetGuidName (
  609. IN SERVERCB *pserver,
  610. IN PWCHAR pszFriendlyName,
  611. IN DWORD dwBufferSize,
  612. OUT PWCHAR pszGuidName )
  613. {
  614. WCHAR pszNoPacketName[1024], pszPacketDesc[64], *pszGuid = NULL;
  615. GUIDMAPCB * pMapCb = (GUIDMAPCB*)(pserver->hGuidMap);
  616. DWORD dwErr;
  617. GUID Guid;
  618. // Validate paramters
  619. if (!pMapCb || !pszFriendlyName || !pszGuidName || !dwBufferSize)
  620. {
  621. return ERROR_INVALID_PARAMETER;
  622. }
  623. // Prepare the map for guid name lookups
  624. dwErr = GuidMapLoad (pMapCb, GUIDMAP_FUNCTION_MAPGUID);
  625. if (dwErr != NO_ERROR)
  626. {
  627. return dwErr;
  628. }
  629. // Nt40 machines require no mapping
  630. if (pMapCb->bNt40)
  631. {
  632. return ERROR_NOT_FOUND;
  633. }
  634. // Remove the packet type from the friendly name
  635. GuidMapParseOutPacketName (
  636. pszFriendlyName,
  637. pszNoPacketName,
  638. pszPacketDesc);
  639. // If we don't have the name in the guid map, then
  640. // this must be a non lan interface.
  641. dwErr = GuidMapLookupGuid (pMapCb, pszNoPacketName, &Guid);
  642. if (dwErr != NO_ERROR)
  643. {
  644. return dwErr;
  645. }
  646. // Otherwise, return its Guid name
  647. do
  648. {
  649. if(RPC_S_OK != UuidToStringW (&Guid, &pszGuid))
  650. {
  651. break;
  652. }
  653. if (pszGuid)
  654. {
  655. dwErr = GuidMapFormatGuidName(
  656. pszGuidName,
  657. dwBufferSize,
  658. pszGuid,
  659. pszPacketDesc);
  660. if ( dwErr != NO_ERROR )
  661. {
  662. if ( pszGuid )
  663. {
  664. RpcStringFreeW (&pszGuid);
  665. pszGuid = NULL;
  666. }
  667. return dwErr;
  668. }
  669. }
  670. } while (FALSE);
  671. // Cleanup
  672. {
  673. if (pszGuid)
  674. {
  675. RpcStringFreeW (&pszGuid);
  676. }
  677. }
  678. return NO_ERROR;
  679. }
  680. //
  681. // States whether a mapping for the given guid name
  682. // exists without actually providing the friendly
  683. // name. This is more efficient than GuidMapGetFriendlyName
  684. // when the friendly name is not required.
  685. //
  686. DWORD
  687. GuidMapIsAdapterInstalled(
  688. IN HANDLE hGuidMap,
  689. IN PWCHAR pszGuidName,
  690. OUT PBOOL pfMappingExists)
  691. {
  692. GUIDMAPCB * pMapCb = (GUIDMAPCB*)hGuidMap;
  693. PWCHAR pszGuidString = NULL, pszNetmanName = NULL;
  694. DWORD dwErr = NO_ERROR, dwSize, dwStatus = 0;
  695. GUID Guid;
  696. // Sanity Check
  697. if (!pMapCb || !pszGuidName)
  698. {
  699. return ERROR_INVALID_PARAMETER;
  700. }
  701. // Prepare the map for friendly name lookups
  702. dwErr = GuidMapLoad (pMapCb, GUIDMAP_FUNCTION_MAPFRIENDLY);
  703. if (dwErr != NO_ERROR)
  704. {
  705. return dwErr;
  706. }
  707. // Nt40 machines require no mapping
  708. if (pMapCb->bNt40)
  709. {
  710. *pfMappingExists = TRUE;
  711. return NO_ERROR;
  712. }
  713. do
  714. {
  715. // Get the guid string from the interface name
  716. dwErr = GuidMapGetGuidString(pszGuidName, &pszGuidString);
  717. if (dwErr != NO_ERROR)
  718. {
  719. break;
  720. }
  721. // If there is no guid, there is no mapping
  722. if (! pszGuidString)
  723. {
  724. dwErr = ERROR_NOT_FOUND;
  725. break;
  726. }
  727. // Convert the guid string
  728. if (UuidFromStringW (pszGuidString, &Guid)!= RPC_S_OK) {
  729. dwErr = ERROR_CAN_NOT_COMPLETE;
  730. break;
  731. }
  732. // Look up the descriptive name
  733. dwErr = GuidMapLookupNameAndStatus (
  734. pMapCb,
  735. &Guid,
  736. &pszNetmanName,
  737. &dwStatus);
  738. if ((dwErr == NO_ERROR) &&
  739. (pszNetmanName) &&
  740. (dwStatus != EL_STATUS_NOT_THERE))
  741. {
  742. *pfMappingExists = TRUE;
  743. }
  744. else
  745. {
  746. *pfMappingExists = FALSE;
  747. }
  748. } while (FALSE);
  749. // Cleanup
  750. {
  751. if (pszGuidString)
  752. {
  753. Free (pszGuidString);
  754. }
  755. }
  756. return dwErr;
  757. }