Source code of Windows XP (NT5)
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.

2448 lines
66 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. miscnt.cxx
  5. Abstract:
  6. This file contains NT specific implementations of miscellaneous
  7. routines.
  8. Author:
  9. Michael Montague (mikemon) 25-Nov-1991
  10. Revision History:
  11. Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
  12. Kamen Moutafov (KamenM) Mar-2000 Support for extended error info
  13. --*/
  14. #include <precomp.hxx>
  15. #include <rpccfg.h>
  16. #include <CharConv.hxx>
  17. static const char *RPC_REGISTRY_PROTOCOLS =
  18. "Software\\Microsoft\\Rpc\\ClientProtocols";
  19. static const char *RPC_REGISTRY_PROTOCOL_IDS =
  20. "Software\\Microsoft\\Rpc\\AdditionalProtocols";
  21. static const RPC_CHAR *RPC_REGISTRY_DEFAULT_SECURITY_DLL =
  22. L"System\\CurrentControlSet\\Control\\SecurityProviders";
  23. // N.B. This value must agree with the key specified in the system.adm file
  24. static const RPC_CHAR *RPC_POLICY_SETTINGS =
  25. L"Software\\Policies\\Microsoft\\Windows NT\\Rpc";
  26. static const RPC_CHAR *RPC_REGISTRY_IMAGE_FILE_EXEC =
  27. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\";
  28. static const RPC_CHAR *RPC_REGISTRY_THREAD_THROTTLE =
  29. L"\\RpcThreadPoolThrottle";
  30. const int IMAGE_FILE_EXEC_LENGTH = 75;
  31. const int THREAD_THROTTLE_LENGTH = 24;
  32. #define MAX_ENDPOINT_LENGTH 128
  33. #define MAX_ID_LENGTH 6
  34. #define MAX_DLL_NAME 128
  35. typedef struct
  36. {
  37. const RPC_CHAR * RpcProtocolSequence;
  38. const RPC_CHAR * TransportInterfaceDll;
  39. unsigned long TransportId;
  40. } RPC_PROTOCOL_SEQUENCE_MAP;
  41. static const RPC_PROTOCOL_SEQUENCE_MAP RpcProtocolSequenceMap[] =
  42. {
  43. {
  44. RPC_CONST_STRING("ncacn_np"),
  45. RPC_CONST_STRING("rpcrt4.dll"),
  46. NMP_TOWER_ID
  47. },
  48. {
  49. RPC_CONST_STRING("ncacn_ip_tcp"),
  50. RPC_CONST_STRING("rpcrt4.dll"),
  51. TCP_TOWER_ID
  52. },
  53. #ifdef SPX_ON
  54. {
  55. RPC_CONST_STRING("ncacn_spx"),
  56. RPC_CONST_STRING("rpcrt4.dll"),
  57. SPX_TOWER_ID
  58. },
  59. #endif
  60. {
  61. RPC_CONST_STRING("ncadg_ip_udp"),
  62. RPC_CONST_STRING("rpcrt4.dll"),
  63. UDP_TOWER_ID
  64. },
  65. #ifdef IPX_ON
  66. {
  67. RPC_CONST_STRING("ncadg_ipx"),
  68. RPC_CONST_STRING("rpcrt4.dll"),
  69. IPX_TOWER_ID
  70. },
  71. #endif
  72. #ifdef NETBIOS_ON
  73. {
  74. RPC_CONST_STRING("ncacn_nb_tcp"),
  75. RPC_CONST_STRING("rpcrt4.dll"),
  76. NB_TOWER_ID
  77. },
  78. {
  79. RPC_CONST_STRING("ncacn_nb_ipx"),
  80. RPC_CONST_STRING("rpcrt4.dll"),
  81. NB_TOWER_ID
  82. },
  83. {
  84. RPC_CONST_STRING("ncacn_nb_nb"),
  85. RPC_CONST_STRING("rpcrt4.dll"),
  86. NB_TOWER_ID
  87. },
  88. #endif
  89. #ifdef APPLETALK_ON
  90. {
  91. RPC_CONST_STRING("ncacn_at_dsp"),
  92. RPC_CONST_STRING("rpcrt4.dll"),
  93. DSP_TOWER_ID
  94. },
  95. #endif
  96. {
  97. RPC_CONST_STRING("ncacn_http"),
  98. RPC_CONST_STRING("rpcrt4.dll"),
  99. HTTP_TOWER_ID
  100. },
  101. {
  102. RPC_CONST_STRING("ncadg_cluster"),
  103. RPC_CONST_STRING("rpcrt4.dll"),
  104. CDP_TOWER_ID
  105. },
  106. #ifdef NCADG_MQ_ON
  107. {
  108. RPC_CONST_STRING("ncadg_mq"),
  109. RPC_CONST_STRING("rpcrt4.dll"),
  110. MQ_TOWER_ID
  111. },
  112. #endif
  113. #ifdef BANYAN_ON
  114. {
  115. RPC_CONST_STRING("ncacn_vns_spp"),
  116. RPC_CONST_STRING("rpcrt4.dll"),
  117. SPP_TOWER_ID
  118. },
  119. #endif
  120. {
  121. RPC_CONST_STRING("ncalrpc"),
  122. 0,
  123. 0
  124. },
  125. };
  126. const int RpcProtseqMapLength = (sizeof(RpcProtocolSequenceMap)
  127. / sizeof(RPC_PROTOCOL_SEQUENCE_MAP));
  128. static const RPC_PROTOCOL_SEQUENCE_MAP RpcUseAllProtseqMap[] =
  129. {
  130. {
  131. RPC_CONST_STRING("ncacn_np"),
  132. RPC_CONST_STRING("rpcrt4.dll"),
  133. NMP_TOWER_ID
  134. },
  135. {
  136. RPC_CONST_STRING("ncalrpc"),
  137. 0,
  138. 0
  139. },
  140. };
  141. const int RpcUseAllProtseqMapLength = (sizeof(RpcUseAllProtseqMap)
  142. / sizeof(RPC_PROTOCOL_SEQUENCE_MAP));
  143. typedef struct
  144. {
  145. unsigned char * RpcProtocolSequence;
  146. unsigned char * RpcSsEndpoint;
  147. unsigned long TransportId;
  148. } RPC_PROTOCOL_INFO;
  149. static const RPC_PROTOCOL_INFO StaticProtocolMapping[] =
  150. {
  151. {
  152. (unsigned char *)"ncacn_np",
  153. (unsigned char *)"\\pipe\\epmapper",
  154. 0x0F
  155. }
  156. };
  157. RPC_PROTOCOL_INFO * AdditionalProtocols = 0;
  158. unsigned long TotalAdditionalProtocols = 0;
  159. static const char *RPC_REGISTRY_SECURITY_PROVIDERS =
  160. "Software\\Microsoft\\Rpc\\SecurityService";
  161. static const char *RPC_MISC_SETTINGS =
  162. "Software\\Microsoft\\Rpc";
  163. BOOL DefaultProviderRead = FALSE;
  164. DWORD DefaultAuthLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  165. DWORD DefaultProviderId = RPC_C_AUTHN_WINNT;
  166. RPC_CHAR *DefaultSecurityDLL = L"secur32.dll";
  167. BOOL DefaultSecurityDLLRead = FALSE;
  168. void
  169. GetMaxRpcSizeAndThreadPoolParameters (
  170. void
  171. )
  172. {
  173. HKEY RegistryKey;
  174. DWORD Result;
  175. DWORD RegStatus;
  176. DWORD Type;
  177. DWORD DwordSize = sizeof(DWORD);
  178. RPC_CHAR KeyName[MAX_PATH + IMAGE_FILE_EXEC_LENGTH + THREAD_THROTTLE_LENGTH];
  179. const RPC_CHAR * ModuleName;
  180. int ModuleLength;
  181. RPC_CHAR *CurrentPos;
  182. //
  183. // Get the default Rpc size.
  184. //
  185. RegStatus = RegOpenKeyExA(
  186. HKEY_LOCAL_MACHINE,
  187. (LPSTR) RPC_MISC_SETTINGS,
  188. 0L, KEY_READ, //Reserved
  189. &RegistryKey
  190. );
  191. if ( RegStatus != ERROR_SUCCESS )
  192. {
  193. return;
  194. }
  195. RegStatus = RegQueryValueExA(
  196. RegistryKey,
  197. "MaxRpcSize",
  198. 0,
  199. &Type,
  200. (LPBYTE) &Result,
  201. &DwordSize
  202. );
  203. if (RegStatus == ERROR_SUCCESS
  204. && Type == REG_DWORD)
  205. {
  206. gMaxRpcSize = Result;
  207. }
  208. RegCloseKey(RegistryKey);
  209. //
  210. // Find out the .EXE name.
  211. //
  212. ModuleName = FastGetImageBaseName();
  213. ModuleLength = RpcpStringLength(ModuleName);
  214. CurrentPos = KeyName;
  215. RpcpMemoryCopy(CurrentPos,
  216. RPC_REGISTRY_IMAGE_FILE_EXEC,
  217. IMAGE_FILE_EXEC_LENGTH * 2);
  218. CurrentPos += IMAGE_FILE_EXEC_LENGTH - 1;
  219. RpcpMemoryCopy(CurrentPos,
  220. ModuleName,
  221. ModuleLength * 2);
  222. CurrentPos += ModuleLength;
  223. RpcpMemoryCopy(CurrentPos,
  224. RPC_REGISTRY_THREAD_THROTTLE,
  225. THREAD_THROTTLE_LENGTH * 2);
  226. RegStatus = RegOpenKeyExW(
  227. HKEY_LOCAL_MACHINE,
  228. KeyName,
  229. 0L, KEY_READ, //Reserved
  230. &RegistryKey
  231. );
  232. if ( RegStatus != ERROR_SUCCESS )
  233. {
  234. return;
  235. }
  236. DwordSize = sizeof(DWORD);
  237. RegStatus = RegQueryValueExA(
  238. RegistryKey,
  239. "ProrateMax",
  240. 0,
  241. &Type,
  242. (LPBYTE) &Result,
  243. &DwordSize
  244. );
  245. if (RegStatus == ERROR_SUCCESS
  246. && Type == REG_DWORD)
  247. {
  248. gProrateMax = Result;
  249. }
  250. DwordSize = sizeof(DWORD);
  251. RegStatus = RegQueryValueExA(
  252. RegistryKey,
  253. "ProrateFactor",
  254. 0,
  255. &Type,
  256. (LPBYTE) &Result,
  257. &DwordSize
  258. );
  259. if (RegStatus == ERROR_SUCCESS
  260. && Type == REG_DWORD)
  261. {
  262. gProrateFactor = Result;
  263. }
  264. DwordSize = sizeof(DWORD);
  265. RegStatus = RegQueryValueExA(
  266. RegistryKey,
  267. "ProrateStart",
  268. 0,
  269. &Type,
  270. (LPBYTE) &Result,
  271. &DwordSize
  272. );
  273. if (RegStatus == ERROR_SUCCESS
  274. && Type == REG_DWORD)
  275. {
  276. gProrateStart = Result;
  277. }
  278. RegCloseKey(RegistryKey);
  279. // if any of these values are invalid, turn it off
  280. if ((gProrateFactor == 0) || (gProrateMax == 0))
  281. gProrateStart = 0;
  282. }
  283. BOOL
  284. GetDefaultLevel()
  285. {
  286. HKEY RegistryKey;
  287. DWORD Result;
  288. DWORD RegStatus;
  289. DWORD Type;
  290. DWORD DwordSize = sizeof(DWORD);
  291. //
  292. // Get the default provider level.
  293. //
  294. RegStatus = RegOpenKeyExA(
  295. HKEY_LOCAL_MACHINE,
  296. (LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
  297. 0L, KEY_READ, //Reserved
  298. &RegistryKey
  299. );
  300. if ( RegStatus != ERROR_SUCCESS )
  301. {
  302. return FALSE;
  303. }
  304. RegStatus = RegQueryValueExA(
  305. RegistryKey,
  306. "DefaultAuthLevel",
  307. 0,
  308. &Type,
  309. (LPBYTE) &Result,
  310. &DwordSize
  311. );
  312. if (RegStatus == ERROR_CANTOPEN ||
  313. RegStatus == ERROR_CANTREAD )
  314. {
  315. RegCloseKey(RegistryKey);
  316. return TRUE;
  317. }
  318. if ( RegStatus != ERROR_SUCCESS )
  319. {
  320. RegCloseKey(RegistryKey);
  321. return FALSE;
  322. }
  323. if ( Type != REG_DWORD )
  324. {
  325. RegCloseKey(RegistryKey);
  326. return TRUE;
  327. }
  328. if (Result >= RPC_C_AUTHN_LEVEL_CONNECT &&
  329. Result <= RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  330. {
  331. DefaultAuthLevel = Result;
  332. }
  333. RegCloseKey(RegistryKey);
  334. return TRUE;
  335. }
  336. void
  337. RpcpGetDefaultSecurityProviderInfo()
  338. {
  339. if (DefaultProviderRead)
  340. {
  341. return;
  342. }
  343. if (GetDefaultLevel())
  344. {
  345. DefaultProviderRead = TRUE;
  346. }
  347. }
  348. RPC_STATUS
  349. GetDefaultSecurityDll (
  350. IN RPC_CHAR *DllName,
  351. IN ULONG DllNameLength
  352. )
  353. {
  354. HKEY RegistryKey;
  355. DWORD RegStatus;
  356. RPC_CHAR *DuplicateDllName;
  357. DWORD Type;
  358. if (DefaultSecurityDLLRead == FALSE)
  359. {
  360. RegStatus = RegOpenKeyEx(
  361. HKEY_LOCAL_MACHINE,
  362. RPC_REGISTRY_DEFAULT_SECURITY_DLL,
  363. 0L, KEY_READ, //Reserved
  364. &RegistryKey
  365. );
  366. if ( RegStatus != ERROR_SUCCESS )
  367. {
  368. if (RegStatus == ERROR_FILE_NOT_FOUND)
  369. {
  370. DefaultSecurityDLLRead = TRUE;
  371. return RPC_S_OK;
  372. }
  373. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  374. }
  375. RegStatus = RegQueryValueEx(
  376. RegistryKey,
  377. L"ClientDll",
  378. 0,
  379. &Type,
  380. (unsigned char *)DllName,
  381. &DllNameLength
  382. );
  383. if ( RegStatus != ERROR_SUCCESS )
  384. {
  385. RegCloseKey(RegistryKey);
  386. if (RegStatus == ERROR_FILE_NOT_FOUND)
  387. {
  388. DefaultSecurityDLLRead = TRUE;
  389. return RPC_S_OK;
  390. }
  391. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  392. }
  393. if (Type != REG_SZ)
  394. {
  395. RegCloseKey(RegistryKey);
  396. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  397. }
  398. DuplicateDllName = DuplicateString(DllName);
  399. RegCloseKey(RegistryKey);
  400. if (DuplicateDllName)
  401. {
  402. DefaultSecurityDLL = DuplicateDllName;
  403. DefaultSecurityDLLRead = TRUE;
  404. }
  405. else
  406. {
  407. return RPC_S_OUT_OF_MEMORY;
  408. }
  409. }
  410. return RPC_S_OK;
  411. }
  412. RPC_STATUS
  413. RpcGetSecurityProviderInfo(
  414. IN unsigned long AuthnId,
  415. OUT RPC_CHAR **Dll,
  416. OUT unsigned long PAPI * Count
  417. )
  418. {
  419. DWORD RegStatus, Ignore, NumberOfValues, MaximumValueLength;
  420. unsigned long DllNameLength = MAX_DLL_NAME+1;
  421. DWORD ClassLength = 64, Type;
  422. RPC_CHAR DllName[MAX_DLL_NAME+1];
  423. FILETIME LastWriteTime;
  424. HKEY RegistryKey;
  425. unsigned char ClassName[64];
  426. RPC_STATUS Status = RPC_S_OK;
  427. char AuthnIdZ[8];
  428. RPC_CHAR unicodeAuthnIdZ[8];
  429. RPC_CHAR *pAuthnIdZ;
  430. RPC_CHAR *ActualDllName;
  431. RpcItoa(AuthnId, AuthnIdZ, 10);
  432. RegStatus = RegOpenKeyExA(
  433. HKEY_LOCAL_MACHINE,
  434. (LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
  435. 0L, KEY_READ, //Reserved
  436. &RegistryKey
  437. );
  438. if ( RegStatus != ERROR_SUCCESS )
  439. {
  440. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  441. }
  442. RegStatus = RegQueryInfoKeyA(
  443. RegistryKey,
  444. (LPSTR) ClassName,
  445. &ClassLength,
  446. 0, //Reserved
  447. &Ignore,
  448. &Ignore,
  449. &Ignore,
  450. &NumberOfValues,
  451. &Ignore,
  452. &MaximumValueLength,
  453. &Ignore,
  454. &LastWriteTime
  455. );
  456. if ( (RegStatus != ERROR_SUCCESS) || (NumberOfValues < 2) )
  457. {
  458. RegStatus = RegCloseKey(RegistryKey);
  459. ASSERT( RegStatus == ERROR_SUCCESS );
  460. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  461. }
  462. *Count = NumberOfValues - 2; //Gross
  463. SimpleAnsiToUnicode(AuthnIdZ, unicodeAuthnIdZ);
  464. pAuthnIdZ = unicodeAuthnIdZ;
  465. RegStatus = RegQueryValueEx(
  466. RegistryKey,
  467. (const RPC_SCHAR *)pAuthnIdZ,
  468. 0,
  469. &Type,
  470. (unsigned char *)DllName,
  471. &DllNameLength
  472. );
  473. RegCloseKey(RegistryKey);
  474. if (RegStatus != ERROR_SUCCESS)
  475. {
  476. RegStatus = GetDefaultSecurityDll(
  477. DllName,
  478. DllNameLength);
  479. if (RegStatus == RPC_S_OK)
  480. ActualDllName = DefaultSecurityDLL;
  481. }
  482. else
  483. {
  484. ActualDllName = DllName;
  485. }
  486. if (RegStatus == ERROR_SUCCESS)
  487. {
  488. *Dll = DuplicateString(ActualDllName);
  489. if (*Dll == 0)
  490. {
  491. RegStatus = RPC_S_OUT_OF_MEMORY;
  492. }
  493. }
  494. else
  495. {
  496. RegStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  497. }
  498. return(RegStatus);
  499. }
  500. DWORD * FourLeggedPackages = 0;
  501. DWORD NullPackageList[] = { 0 };
  502. BOOL
  503. ReadPackageLegInfo()
  504. /*++
  505. Routine Description:
  506. NT 4.0 and previous versions allowed only two or three legs to set up the
  507. security context. Two were represented on the wire as BIND then BIND_ACK;
  508. three added an AUTH3 packet. When Jeff added 4- and 6-leg support, he
  509. made the sequence BIND, BIND-ACK, ALTER-CXT, ALTER-CXT-RESPONSE. Sadly,
  510. it turns out to be impossible for RPC to tell whether a given package wants
  511. three or four legs, so the client would have to guess whether to send
  512. an AUTH3 or an ALTER-CXT to an NT 4 server. To solve this we are adding a
  513. registry value that lists all the providers that need more than three legs.
  514. The format, in regdmp.exe form, is
  515. \Registry\Machine\Software\Microsoft\Rpc
  516. Four-legged packages = REG_MULTI_SZ "16" "18" ""
  517. This function opens the registry and converts this data into an in-memory
  518. array of DWORD package IDs.
  519. Not all packages are in this list; see GetPackageLegCount() for details.
  520. Return Values:
  521. TRUE = the registry data was read, or the value does not exist.
  522. Calling this function again will have no effect.
  523. FALSE = there was a problem reading the data in the registry.
  524. You can call the fn later and it will try again.
  525. --*/
  526. {
  527. DWORD Size = 0;
  528. DWORD RegStatus;
  529. DWORD Type;
  530. HKEY RegistryKey;
  531. wchar_t * Strings;
  532. if (FourLeggedPackages)
  533. {
  534. return TRUE;
  535. }
  536. SecurityCritSect->VerifyOwned();
  537. // open key;
  538. RegStatus = RegOpenKeyExA(
  539. HKEY_LOCAL_MACHINE,
  540. (LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
  541. 0L, KEY_READ, //Reserved
  542. &RegistryKey
  543. );
  544. if ( RegStatus != ERROR_SUCCESS )
  545. {
  546. return FALSE;
  547. }
  548. // get size of strings
  549. RegStatus = RegQueryValueExW(
  550. RegistryKey,
  551. L"Four-legged packages",
  552. 0,
  553. &Type,
  554. 0,
  555. &Size
  556. );
  557. if (RegStatus == ERROR_FILE_NOT_FOUND )
  558. {
  559. RegCloseKey(RegistryKey);
  560. FourLeggedPackages = NullPackageList;
  561. return TRUE;
  562. }
  563. if ( RegStatus != ERROR_SUCCESS )
  564. {
  565. RegCloseKey(RegistryKey);
  566. return FALSE;
  567. }
  568. //
  569. // Place an upper bound on the size to avoid hacker attacks.
  570. //
  571. if ( Type != REG_MULTI_SZ || Size > 4000)
  572. {
  573. RegCloseKey(RegistryKey);
  574. FourLeggedPackages = NullPackageList;
  575. return TRUE;
  576. }
  577. // get string data.
  578. Strings = (wchar_t *) _alloca( Size );
  579. RegStatus = RegQueryValueExW(
  580. RegistryKey,
  581. L"Four-legged packages",
  582. 0,
  583. &Type,
  584. (unsigned char *) Strings,
  585. &Size
  586. );
  587. RegCloseKey(RegistryKey);
  588. if (RegStatus == ERROR_CANTOPEN ||
  589. RegStatus == ERROR_CANTREAD )
  590. {
  591. FourLeggedPackages = NullPackageList;
  592. return TRUE;
  593. }
  594. if ( RegStatus != ERROR_SUCCESS )
  595. {
  596. return FALSE;
  597. }
  598. if ( Type != REG_MULTI_SZ )
  599. {
  600. FourLeggedPackages = NullPackageList;
  601. return TRUE;
  602. }
  603. // count strings; the buffer is terminated by an empty string that will be counted.
  604. int Count = 0;
  605. wchar_t * p;
  606. for (p=Strings; p < Strings + Size; ++p)
  607. {
  608. if (*p == '\0')
  609. {
  610. ++Count;
  611. }
  612. }
  613. // allocate memory.
  614. DWORD * LegData = new DWORD[Count];
  615. if (!LegData)
  616. {
  617. return FALSE;
  618. }
  619. // transfer data
  620. int i;
  621. wchar_t * new_p;
  622. for (i=0, p=Strings; p < Strings + Size; ++i, p = new_p+1)
  623. {
  624. LegData[i] = wcstoul(p, &new_p, 10);
  625. if (*new_p != '\0')
  626. {
  627. // The string is badly formatted. Eliminate it.
  628. --i;
  629. new_p += wcslen(new_p);
  630. }
  631. }
  632. if (FourLeggedPackages && FourLeggedPackages != NullPackageList)
  633. {
  634. delete FourLeggedPackages;
  635. }
  636. FourLeggedPackages = LegData;
  637. return TRUE;
  638. }
  639. RPC_STATUS
  640. LoadAdditionalTransportInfo(
  641. )
  642. {
  643. DWORD RegStatus, Index, Ignore, NumberOfValues, MaximumValueLength;
  644. DWORD ClassLength = 64, ProtseqLength, IgnoreLength;
  645. BYTE Protseq[MAX_PROTSEQ_LENGTH+1];
  646. BYTE MaxValueData[MAX_ENDPOINT_LENGTH+MAX_ID_LENGTH+2+8];
  647. FILETIME LastWriteTime;
  648. HKEY RegistryKey;
  649. unsigned char ClassName[64];
  650. char * Value;
  651. RPC_PROTOCOL_INFO * AdditionalProtocolsInfo;
  652. RPC_STATUS Status = RPC_S_OK;
  653. unsigned long Length, TransportId;
  654. RegStatus = RegOpenKeyExA(
  655. HKEY_LOCAL_MACHINE,
  656. (LPSTR) RPC_REGISTRY_PROTOCOL_IDS,
  657. 0L, KEY_READ, //Reserved
  658. &RegistryKey
  659. );
  660. if ( RegStatus != ERROR_SUCCESS )
  661. {
  662. return(RPC_S_INVALID_RPC_PROTSEQ);
  663. }
  664. RegStatus = RegQueryInfoKeyA(
  665. RegistryKey,
  666. (LPSTR) ClassName,
  667. &ClassLength,
  668. 0, //Reserved
  669. &Ignore,
  670. &Ignore,
  671. &Ignore,
  672. &NumberOfValues,
  673. &Ignore,
  674. &MaximumValueLength,
  675. &Ignore,
  676. &LastWriteTime
  677. );
  678. if ( (RegStatus != ERROR_SUCCESS) || (NumberOfValues == 0) )
  679. {
  680. RegStatus = RegCloseKey(RegistryKey);
  681. ASSERT( RegStatus == ERROR_SUCCESS );
  682. return(RPC_S_INVALID_RPC_PROTSEQ);
  683. }
  684. //Allocate a table for additional transports mapping
  685. AdditionalProtocolsInfo = (RPC_PROTOCOL_INFO *) new unsigned char [
  686. sizeof(RPC_PROTOCOL_INFO) * NumberOfValues];
  687. if (AdditionalProtocolsInfo == 0)
  688. {
  689. Status = RPC_S_OUT_OF_MEMORY;
  690. goto Cleanup;
  691. }
  692. AdditionalProtocols = AdditionalProtocolsInfo;
  693. TotalAdditionalProtocols = NumberOfValues;
  694. for (Index = 0; Index < NumberOfValues; Index++)
  695. {
  696. ProtseqLength = MAX_PROTSEQ_LENGTH;
  697. IgnoreLength = MAX_ENDPOINT_LENGTH + MAX_ID_LENGTH;
  698. RegStatus = RegEnumValueA(
  699. RegistryKey,
  700. Index,
  701. (LPSTR) &Protseq,
  702. &ProtseqLength,
  703. 0,
  704. &Ignore,
  705. (LPBYTE) MaxValueData,
  706. &IgnoreLength
  707. );
  708. if (RegStatus == ERROR_SUCCESS)
  709. {
  710. //Add this to our table..
  711. AdditionalProtocolsInfo->RpcProtocolSequence =
  712. new unsigned char[ProtseqLength+1];
  713. Value = (char * )&MaxValueData;
  714. AdditionalProtocolsInfo->RpcSsEndpoint =
  715. new unsigned char[Length = (strlen(Value) + 1)];
  716. if (AdditionalProtocolsInfo->RpcProtocolSequence == 0
  717. || AdditionalProtocolsInfo->RpcSsEndpoint == 0)
  718. {
  719. Status = RPC_S_OUT_OF_MEMORY;
  720. goto Cleanup;
  721. }
  722. RpcpMemoryCopy(
  723. AdditionalProtocolsInfo->RpcProtocolSequence,
  724. Protseq,
  725. ProtseqLength+1
  726. );
  727. RpcpMemoryCopy(
  728. AdditionalProtocolsInfo->RpcSsEndpoint,
  729. Value,
  730. Length
  731. );
  732. Value = Value + Length;
  733. for (TransportId = 0;
  734. (*Value > '0') && (*Value <= '9') && (TransportId <= 255);
  735. Value++)
  736. {
  737. TransportId = TransportId * 10 + (*Value - '0');
  738. }
  739. AdditionalProtocolsInfo->TransportId = TransportId;
  740. AdditionalProtocolsInfo++;
  741. }
  742. }
  743. Cleanup:
  744. RegStatus = RegCloseKey(RegistryKey);
  745. if (Status != RPC_S_OK)
  746. {
  747. if (AdditionalProtocols != 0)
  748. {
  749. AdditionalProtocolsInfo = AdditionalProtocols;
  750. for (Index = 0; Index < NumberOfValues; Index++)
  751. {
  752. if (AdditionalProtocolsInfo->RpcProtocolSequence != 0)
  753. delete AdditionalProtocolsInfo->RpcProtocolSequence;
  754. if (AdditionalProtocolsInfo->RpcSsEndpoint != 0)
  755. delete AdditionalProtocolsInfo->RpcSsEndpoint;
  756. AdditionalProtocolsInfo++;
  757. }
  758. delete AdditionalProtocols;
  759. AdditionalProtocols = 0;
  760. TotalAdditionalProtocols = 0;
  761. }
  762. }
  763. return(Status);
  764. }
  765. RPC_STATUS
  766. RpcGetAdditionalTransportInfo(
  767. IN unsigned long TransportId,
  768. OUT unsigned char PAPI * PAPI * ProtocolSequence
  769. )
  770. {
  771. unsigned long i;
  772. RPC_PROTOCOL_INFO * ProtocolInfo;
  773. RequestGlobalMutex();
  774. if (AdditionalProtocols == 0)
  775. {
  776. LoadAdditionalTransportInfo();
  777. }
  778. ClearGlobalMutex();
  779. for (i = 0, ProtocolInfo = AdditionalProtocols ;
  780. i < TotalAdditionalProtocols;
  781. i++)
  782. {
  783. if (ProtocolInfo->TransportId == TransportId)
  784. {
  785. *ProtocolSequence = ProtocolInfo->RpcProtocolSequence;
  786. return (RPC_S_OK);
  787. }
  788. ProtocolInfo ++;
  789. }
  790. return(RPC_S_INVALID_RPC_PROTSEQ);
  791. }
  792. RPC_CHAR *
  793. LocalMapRpcProtocolSequence (
  794. IN RPC_CHAR PAPI * RpcProtocolSequence
  795. )
  796. /*++
  797. Routine Description:
  798. We need to check the supplied protocol sequence (and module) to see
  799. if we can map them into a transport interface dll without having to
  800. use the registry.
  801. Arguments:
  802. ServerSideFlag - Supplies a flag indicating whether this protocol
  803. sequence is to be mapped for a client or a server; a non-zero
  804. value indicates that it is being mapped for a server.
  805. RpcProtocolSequence - Supplies the protocol sequence which we need to
  806. map into a transport interface dll.
  807. Return Value:
  808. If we successfully map the protocol sequence, then a pointer to a static
  809. string containing the transport interface dll (name) will be returned;
  810. the caller must duplicate the string. Otherwise, zero will be returned.
  811. --*/
  812. {
  813. unsigned int Index;
  814. for (Index = 0; Index < RpcProtseqMapLength; Index++)
  815. {
  816. if ( RpcpStringCompare(RpcProtocolSequence,
  817. RpcProtocolSequenceMap[Index].RpcProtocolSequence) == 0 )
  818. {
  819. return((RPC_CHAR *)(RpcProtocolSequenceMap[Index].TransportInterfaceDll));
  820. }
  821. }
  822. return(0);
  823. }
  824. RPC_STATUS
  825. RpcGetWellKnownTransportInfo(
  826. IN unsigned long TransportId,
  827. OUT RPC_CHAR **PSeq
  828. )
  829. {
  830. unsigned int Index;
  831. for (Index = 0; Index < RpcProtseqMapLength; Index++)
  832. {
  833. if (TransportId == RpcProtocolSequenceMap[Index].TransportId)
  834. {
  835. *PSeq = (RPC_CHAR *)RpcProtocolSequenceMap[Index].RpcProtocolSequence;
  836. return RPC_S_OK;
  837. }
  838. }
  839. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  840. }
  841. RPC_STATUS
  842. RpcConfigMapRpcProtocolSequence (
  843. IN unsigned int ServerSideFlag,
  844. IN RPC_CHAR PAPI * RpcProtocolSequence,
  845. OUT RPC_CHAR * PAPI * TransportInterfaceDll
  846. )
  847. /*++
  848. Routine Description:
  849. This routine is used by the rpc protocol modules to map from an
  850. rpc protocol sequence to the name of a transport interface dll.
  851. Arguments:
  852. ServerSideFlag - Supplies a flag indicating whether this protocol
  853. sequence is to be mapped for a client or a server; a non-zero
  854. value indicates that it is being mapped for a server.
  855. RpcProtocolSequence - Supplies the rpc protocol sequence to map.
  856. TransportInterfaceDll - Returns the transport support dll which
  857. supports the requested rpc protocol sequence. This will be a
  858. newly allocated string which the caller must free.
  859. Return Value:
  860. RPC_S_OK - Everything worked out fine.
  861. RPC_S_PROTSEQ_NOT_SUPPORTED - The requested rpc protocol sequence
  862. does not have a mapping to a transport interface dll for this
  863. rpc protocol module.
  864. RPC_S_OUT_OF_MEMORY - We ran out of memory trying to map the rpc
  865. protocol sequence.
  866. --*/
  867. {
  868. RPC_CHAR * TempString;
  869. HKEY RegistryKey;
  870. DWORD Type;
  871. long RegStatus;
  872. unsigned char * KeyString;
  873. unsigned long Length;
  874. TempString = LocalMapRpcProtocolSequence(RpcProtocolSequence);
  875. if ( TempString != 0 )
  876. {
  877. *TransportInterfaceDll = new RPC_CHAR[RpcpStringLength(TempString) + 1];
  878. if ( *TransportInterfaceDll == 0 )
  879. {
  880. return(RPC_S_OUT_OF_MEMORY);
  881. }
  882. memcpy(*TransportInterfaceDll, TempString,
  883. (RpcpStringLength(TempString) + 1) * sizeof(RPC_CHAR));
  884. return(RPC_S_OK);
  885. }
  886. KeyString = (unsigned char *) RPC_REGISTRY_PROTOCOLS;
  887. RegStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE, (LPSTR) KeyString, 0L,
  888. KEY_READ, &RegistryKey);
  889. if ( RegStatus != ERROR_SUCCESS )
  890. {
  891. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  892. }
  893. *TransportInterfaceDll = new RPC_CHAR[MAX_DLLNAME_LENGTH + 1];
  894. if ( *TransportInterfaceDll == 0 )
  895. {
  896. RegStatus = RegCloseKey(RegistryKey);
  897. ASSERT( RegStatus == ERROR_SUCCESS );
  898. return(RPC_S_OUT_OF_MEMORY);
  899. }
  900. Length = (MAX_DLLNAME_LENGTH + 1) * sizeof(RPC_CHAR);
  901. RegStatus = RegQueryValueEx(RegistryKey, (const RPC_SCHAR *)RpcProtocolSequence,
  902. 0, &Type, (LPBYTE) *TransportInterfaceDll, &Length);
  903. if ( RegStatus == ERROR_SUCCESS )
  904. {
  905. RegStatus = RegCloseKey(RegistryKey);
  906. ASSERT( RegStatus == ERROR_SUCCESS );
  907. return(RPC_S_OK);
  908. }
  909. RegStatus = RegCloseKey(RegistryKey);
  910. ASSERT( RegStatus == ERROR_SUCCESS );
  911. delete *TransportInterfaceDll;
  912. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  913. }
  914. RPC_STATUS
  915. RpcConfigInquireProtocolSequencesFromKey (
  916. OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector,
  917. unsigned char *RegistryKeyName
  918. )
  919. /*++
  920. Routine Description:
  921. This routine is used to obtain a list of the rpc protocol sequences
  922. supported by the system using a given registry key as a reference
  923. point.
  924. Arguments:
  925. ProtseqVector - Returns a vector of supported rpc protocol sequences
  926. for this rpc protocol module.
  927. RegistryKeyName - the path of the registry key, starting from
  928. HKLM (the HKLM itself should not be supplied)
  929. Return Value:
  930. RPC_S_OK - The operation completed successfully.
  931. RPC_S_NO_PROTSEQS - The current system configuration does not
  932. support any rpc protocol sequences.
  933. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire
  934. the rpc protocol sequences supported by the specified rpc
  935. protocol sequence.
  936. --*/
  937. {
  938. DWORD RegStatus, Index, Ignore, MaximumValueLength;
  939. DWORD ClassLength = 64, ProtseqLength, IgnoreLength;
  940. BYTE IgnoreData[MAX_DLLNAME_LENGTH];
  941. FILETIME LastWriteTime;
  942. HKEY RegistryKey = 0;
  943. unsigned char ClassName[64];
  944. DWORD NumberOfValues = 0;
  945. RegStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  946. (LPSTR) RegistryKeyName, 0L, KEY_READ, &RegistryKey);
  947. if ( RegStatus != ERROR_SUCCESS )
  948. {
  949. return(RPC_S_NO_PROTSEQS);
  950. }
  951. RegStatus = RegQueryInfoKeyA(RegistryKey, (LPSTR) ClassName, &ClassLength,
  952. 0, &Ignore, &Ignore, &Ignore, &NumberOfValues,
  953. &Ignore, &MaximumValueLength, &Ignore, &LastWriteTime);
  954. ASSERT( RegStatus == ERROR_SUCCESS );
  955. if ( RegStatus != ERROR_SUCCESS )
  956. {
  957. RegStatus = RegCloseKey(RegistryKey);
  958. ASSERT( RegStatus == ERROR_SUCCESS );
  959. return(RPC_S_NO_PROTSEQS);
  960. }
  961. NumberOfValues += RpcUseAllProtseqMapLength;
  962. *ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
  963. sizeof(RPC_PROTSEQ_VECTOR) + (NumberOfValues - 1)
  964. * sizeof(RPC_CHAR *)];
  965. if ( *ProtseqVector == 0 )
  966. {
  967. RegStatus = RegCloseKey(RegistryKey);
  968. ASSERT( RegStatus == ERROR_SUCCESS );
  969. return(RPC_S_OUT_OF_MEMORY);
  970. }
  971. (*ProtseqVector)->Count = (unsigned int) NumberOfValues;
  972. for (Index = 0; Index < NumberOfValues; Index++)
  973. {
  974. (*ProtseqVector)->Protseq[Index] = 0;
  975. }
  976. for (Index = 0; Index < RpcUseAllProtseqMapLength; Index++)
  977. {
  978. (*ProtseqVector)->Protseq[Index] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
  979. if ( (*ProtseqVector)->Protseq[Index] == 0 )
  980. {
  981. RegStatus = RegCloseKey(RegistryKey);
  982. ASSERT( RegStatus == ERROR_SUCCESS );
  983. RpcProtseqVectorFree(ProtseqVector);
  984. return(RPC_S_OUT_OF_MEMORY);
  985. }
  986. RpcpStringCopy((*ProtseqVector)->Protseq[Index],
  987. RpcUseAllProtseqMap[Index].RpcProtocolSequence);
  988. }
  989. unsigned VectorIndex = Index;
  990. for (Index = 0; VectorIndex < NumberOfValues; Index++, VectorIndex++)
  991. {
  992. (*ProtseqVector)->Protseq[VectorIndex] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
  993. if ( (*ProtseqVector)->Protseq[VectorIndex] == 0 )
  994. {
  995. RegStatus = RegCloseKey(RegistryKey);
  996. ASSERT( RegStatus == ERROR_SUCCESS );
  997. RpcProtseqVectorFree(ProtseqVector);
  998. return(RPC_S_OUT_OF_MEMORY);
  999. }
  1000. ProtseqLength = MAX_PROTSEQ_LENGTH;
  1001. IgnoreLength = MAX_DLLNAME_LENGTH;
  1002. RegStatus = RegEnumValue(RegistryKey, Index,
  1003. (RPC_SCHAR *)(*ProtseqVector)->Protseq[VectorIndex], &ProtseqLength,
  1004. 0, &Ignore, (LPBYTE) IgnoreData, &IgnoreLength);
  1005. ASSERT( RegStatus == ERROR_SUCCESS );
  1006. if (RpcpStringCompare((RPC_SCHAR *)(*ProtseqVector)->Protseq[VectorIndex], RPC_T("ncacn_np")) == 0)
  1007. {
  1008. // ignore this named pipe value - we have to have it in the registry for
  1009. // compatibility purposes with VB, but we don't really use it
  1010. NumberOfValues --;
  1011. (*ProtseqVector)->Count --;
  1012. delete (*ProtseqVector)->Protseq[VectorIndex];
  1013. VectorIndex --;
  1014. }
  1015. }
  1016. RegStatus = RegCloseKey(RegistryKey);
  1017. ASSERT( RegStatus == ERROR_SUCCESS );
  1018. return(RPC_S_OK);
  1019. }
  1020. RPC_STATUS RpcConfigInquireStaticProtocolSequences(RPC_PROTSEQ_VECTOR **ProtseqVector)
  1021. /*++
  1022. Routine Description:
  1023. Returns a protseq vector that contains all the protseqs in the static RpcProtocolSequenceMap
  1024. map.
  1025. Arguments:
  1026. ProtseqVector - Returns a vector of supported rpc protocol sequences.
  1027. Return Value:
  1028. RPC_S_OK - The operation completed successfully.
  1029. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to construct the vector.
  1030. --*/
  1031. {
  1032. int nNumberOfValues = sizeof(RpcProtocolSequenceMap) / sizeof(RpcProtocolSequenceMap[0]);
  1033. int i;
  1034. *ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
  1035. sizeof(RPC_PROTSEQ_VECTOR) + (nNumberOfValues - 1)
  1036. * sizeof(RPC_CHAR *)];
  1037. if ( *ProtseqVector == 0 )
  1038. return(RPC_S_OUT_OF_MEMORY);
  1039. (*ProtseqVector)->Count = (unsigned int) nNumberOfValues;
  1040. for (i = 0; i < nNumberOfValues; i ++)
  1041. {
  1042. (*ProtseqVector)->Protseq[i] = NULL;
  1043. }
  1044. for (i = 0; i < nNumberOfValues; i ++)
  1045. {
  1046. (*ProtseqVector)->Protseq[i] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
  1047. if ( (*ProtseqVector)->Protseq[i] == 0 )
  1048. {
  1049. RpcProtseqVectorFree(ProtseqVector);
  1050. return(RPC_S_OUT_OF_MEMORY);
  1051. }
  1052. RpcpStringCopy((*ProtseqVector)->Protseq[i],
  1053. RpcProtocolSequenceMap[i].RpcProtocolSequence);
  1054. }
  1055. return RPC_S_OK;
  1056. }
  1057. int MarkDuplicateEntries(IN RPC_PROTSEQ_VECTOR *ProtseqVector1,
  1058. IN int nVector1CurrentPos,
  1059. IN RPC_PROTSEQ_VECTOR *ProtseqVector2 OPTIONAL,
  1060. IN OUT UCHAR *pfDuplicates1,
  1061. IN OUT UCHAR *pfDuplicates2)
  1062. /*++
  1063. Routine Description:
  1064. This routine is tightly coupled with RpcConfigInquireProtocolSequences.
  1065. If the current element is already marked as duplicate by previous
  1066. run of this function, we directly return 1. If not,
  1067. it checks whether the current element is duplicate of any element
  1068. starting with the nVetcor1StartingPos from the first vector, and
  1069. going through the whole second vector if it is there, and marking
  1070. all duplicates of the current element as such. Then 0 is returned.
  1071. If the second vector is NULL, the pfDuplicates2 must be NULL also. This
  1072. means that there is one vector only, and its data are passed in
  1073. in RpcProtseqVector1 and in pfDuplicates1.
  1074. Arguments:
  1075. RpcProtseqVector1 - the first vector
  1076. nVector1CurrentPos - the current position from the first vector
  1077. RpcProtseqVector2 - the second vector. This argument may be null
  1078. pfDuplicates1 - the array of duplicate flags for the first vector
  1079. pfDuplicates2 - the array of duplicate flags for the second vector. If
  1080. second vector is NULL, must be NULL also.
  1081. Return Value:
  1082. 1 - the current element is a duplicate of an element that we
  1083. encountered in a previous run of this function.
  1084. 0 - the current element is unique in both vectors
  1085. --*/
  1086. {
  1087. int i;
  1088. RPC_CHAR *pszCurrentElement;
  1089. ASSERT(nVector1CurrentPos < (int)ProtseqVector1->Count);
  1090. if (pfDuplicates1[nVector1CurrentPos])
  1091. return 1;
  1092. pszCurrentElement = ProtseqVector1->Protseq[nVector1CurrentPos];
  1093. for (i = nVector1CurrentPos + 1; i < (int)ProtseqVector1->Count; i ++)
  1094. {
  1095. if (RpcpStringCompare(pszCurrentElement,
  1096. ProtseqVector1->Protseq[i]) == 0)
  1097. {
  1098. pfDuplicates1[i] = TRUE;
  1099. }
  1100. }
  1101. if (ProtseqVector2)
  1102. {
  1103. ASSERT(pfDuplicates2 != NULL);
  1104. for (i = 0; i < (int)ProtseqVector2->Count; i ++)
  1105. {
  1106. if (RpcpStringCompare(pszCurrentElement,
  1107. ProtseqVector2->Protseq[i]) == 0)
  1108. {
  1109. pfDuplicates2[i] = TRUE;
  1110. }
  1111. }
  1112. }
  1113. else
  1114. {
  1115. ASSERT(pfDuplicates2 == NULL);
  1116. }
  1117. return 0;
  1118. }
  1119. RPC_STATUS
  1120. MergeProtseqVectors (IN OUT RPC_PROTSEQ_VECTOR *ProtseqVector1,
  1121. IN OUT RPC_PROTSEQ_VECTOR *ProtseqVector2 OPTIONAL,
  1122. OUT RPC_PROTSEQ_VECTOR **ProtseqVector
  1123. )
  1124. /*++
  1125. Routine Description:
  1126. This routine takes two protseq vectors, and in the OUT argument ProtseqVector
  1127. returns the resulting vector, which is a union of the two IN
  1128. vectors. Successful or not, the input vectors will be freed on exit.
  1129. Arguments:
  1130. ProtseqVector1 - the first vector
  1131. ProtseqVector2 - the second vector. This argument may be null in which case the
  1132. output vector is simply the first vector.
  1133. ProtseqVector - the resulting union vector. If the return value from the function
  1134. is not RPC_S_OK, the out parameter is undefined and should not be used by caller.
  1135. Return Value:
  1136. RPC_S_OK - success. The ProtseqVector argument contains the resulting vector.
  1137. error code - the cause of the error.
  1138. --*/
  1139. {
  1140. unsigned char *pfDuplicate1;
  1141. unsigned char *pfDuplicate2;
  1142. int i, j;
  1143. int nDuplicateElements;
  1144. int nCurrentElement;
  1145. int nUniqueElements;
  1146. // compare basically each with each
  1147. // construct arrays in which we will mark each duplicate element
  1148. // if it is such
  1149. pfDuplicate1 = (unsigned char *)alloca(ProtseqVector1->Count);
  1150. if (ProtseqVector2)
  1151. pfDuplicate2 = (unsigned char *)alloca(ProtseqVector2->Count);
  1152. else
  1153. pfDuplicate2 = NULL;
  1154. // all elements are presumed to be unique unless proven otherwise
  1155. memset(pfDuplicate1, 0, ProtseqVector1->Count);
  1156. if (ProtseqVector2)
  1157. memset(pfDuplicate2, 0, ProtseqVector2->Count);
  1158. nDuplicateElements = 0;
  1159. // do compare each with each
  1160. // test the first vector for uniqueness
  1161. for (i = 0; i < (int)ProtseqVector1->Count; i ++)
  1162. {
  1163. nDuplicateElements += MarkDuplicateEntries(ProtseqVector1, i,
  1164. ProtseqVector2, pfDuplicate1, pfDuplicate2);
  1165. }
  1166. if (ProtseqVector2)
  1167. {
  1168. // test the second vector for uniqueness
  1169. for (i = 0; i < (int)ProtseqVector2->Count; i ++)
  1170. {
  1171. nDuplicateElements += MarkDuplicateEntries(ProtseqVector2, i,
  1172. NULL, pfDuplicate2, NULL);
  1173. }
  1174. }
  1175. // here we must move the unique elements to a new vector
  1176. // first, calculate the length of the new vector
  1177. nUniqueElements = ProtseqVector1->Count - nDuplicateElements;
  1178. if (ProtseqVector2)
  1179. nUniqueElements += ProtseqVector2->Count;
  1180. // second, alloc the new vector
  1181. *ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
  1182. sizeof(RPC_PROTSEQ_VECTOR) +
  1183. (nUniqueElements - 1) * sizeof(RPC_CHAR *)];
  1184. if (*ProtseqVector == NULL)
  1185. {
  1186. RpcProtseqVectorFree(&ProtseqVector1);
  1187. if (ProtseqVector2)
  1188. RpcProtseqVectorFree(&ProtseqVector2);
  1189. return RPC_S_OUT_OF_MEMORY;
  1190. }
  1191. // set the count of the union vector
  1192. (*ProtseqVector)->Count = nUniqueElements;
  1193. nCurrentElement = 0; // counts the current element in the union
  1194. // vector
  1195. for (i = 0; i < (int)ProtseqVector1->Count; i ++)
  1196. {
  1197. if (!pfDuplicate1[i])
  1198. {
  1199. (*ProtseqVector)->Protseq[nCurrentElement] =
  1200. ProtseqVector1->Protseq[i];
  1201. nCurrentElement ++;
  1202. // save the string from deletion
  1203. ProtseqVector1->Protseq[i] = NULL;
  1204. }
  1205. }
  1206. if (ProtseqVector2)
  1207. {
  1208. for (i = 0; i < (int)ProtseqVector2->Count; i ++)
  1209. {
  1210. if (!pfDuplicate2[i])
  1211. {
  1212. (*ProtseqVector)->Protseq[nCurrentElement] =
  1213. ProtseqVector2->Protseq[i];
  1214. nCurrentElement ++;
  1215. // save the string from deletion
  1216. ProtseqVector2->Protseq[i] = NULL;
  1217. }
  1218. }
  1219. }
  1220. // we don't need the original vectors anymore - delete them
  1221. RpcProtseqVectorFree(&ProtseqVector1);
  1222. if (ProtseqVector2)
  1223. RpcProtseqVectorFree(&ProtseqVector2);
  1224. return RPC_S_OK;
  1225. }
  1226. RPC_STATUS
  1227. RpcConfigInquireProtocolSequences (
  1228. IN BOOL fGetAllProtseqs,
  1229. OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector1
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. This routine is used to obtain a list of the rpc protocol sequences
  1234. supported by the system.
  1235. Arguments:
  1236. fGetAllProtseqs - if TRUE, all protseqs known will be returned. If FALSE,
  1237. only the protseqs currently installed will be returned.
  1238. ProtseqVector - Returns a vector of supported rpc protocol sequences
  1239. for this rpc protocol module.
  1240. Return Value:
  1241. RPC_S_OK - The operation completed successfully.
  1242. RPC_S_NO_PROTSEQS - The current system configuration does not
  1243. support any rpc protocol sequences.
  1244. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire
  1245. the rpc protocol sequences supported by rpc.
  1246. --*/
  1247. {
  1248. RPC_STATUS RpcStatus1;
  1249. RPC_STATUS RpcStatus2;
  1250. RPC_PROTSEQ_VECTOR *ProtseqVector2 = NULL;
  1251. RPC_PROTSEQ_VECTOR *ProtseqVector;
  1252. if (fGetAllProtseqs)
  1253. {
  1254. RpcStatus2 = RpcConfigInquireStaticProtocolSequences(&ProtseqVector2);
  1255. if (RpcStatus2 != RPC_S_OK)
  1256. return RpcStatus2;
  1257. }
  1258. // under NT, failure to query the registry vector is fatal. Under Win98, querying
  1259. // this registry vector is optional, and if we fail, we have to continue gathering the
  1260. // vector from other sources.
  1261. RpcStatus1 = RpcConfigInquireProtocolSequencesFromKey(
  1262. ProtseqVector1, (unsigned char *)RPC_REGISTRY_PROTOCOLS);
  1263. if (RpcStatus1 != RPC_S_OK)
  1264. {
  1265. RpcProtseqVectorFree(&ProtseqVector2);
  1266. return RpcStatus1;
  1267. }
  1268. if (fGetAllProtseqs)
  1269. {
  1270. // Merge the static vector and the one from the registry
  1271. RpcStatus1 = MergeProtseqVectors(*ProtseqVector1, ProtseqVector2, &ProtseqVector);
  1272. if (RpcStatus1 != RPC_S_OK)
  1273. {
  1274. return RpcStatus1;
  1275. }
  1276. *ProtseqVector1 = ProtseqVector;
  1277. }
  1278. return RpcStatus1;
  1279. }
  1280. // N.B. This enumration must agree with the values
  1281. // in system.adm
  1282. typedef enum tagStateInformationPolicyValues
  1283. {
  1284. sipvNone,
  1285. sipvAuto1,
  1286. sipvAuto2,
  1287. sipvServer,
  1288. sipvFull
  1289. } StateInformationPolicyValues;
  1290. // N.B. This enumration must agree with the values
  1291. // in system.adm
  1292. typedef enum tagEEInfoPolicyValues
  1293. {
  1294. eeipvOff,
  1295. eeipvOnWithExceptions,
  1296. eeipvOffWithExceptions,
  1297. eeipvOn
  1298. } EEInfoPolicyValues;
  1299. void
  1300. SetAutoPolicySettings(
  1301. StateInformationPolicyValues PolicyValue
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. This routine sets the state information maintenance to the appropriate
  1306. level of Auto, depending on machine capacity.
  1307. Arguments:
  1308. PolicyValue - sipvAuto1 or sipvAuto2
  1309. Return Value:
  1310. RPC_S_OK - The operation completed successfully.
  1311. other RPC_S_* - error
  1312. --*/
  1313. {
  1314. NT_PRODUCT_TYPE ProductType;
  1315. BOOL fNeedServer;
  1316. ULONG_PTR MinMemoryNeeded;
  1317. MEMORYSTATUSEX MemoryStatus;
  1318. BOOL fResult;
  1319. ASSERT((PolicyValue == sipvAuto1) || (PolicyValue == sipvAuto2));
  1320. // client side debug info is FALSE by default - no need to
  1321. // set it explicitly
  1322. // see what we have
  1323. // RtlGetNtProductType always returns valid ProductType
  1324. // It may be incorrect during GUI mode setup, but it will
  1325. // be valid
  1326. (VOID) RtlGetNtProductType(&ProductType);
  1327. MemoryStatus.dwLength = sizeof(MemoryStatus);
  1328. fResult = GlobalMemoryStatusEx(&MemoryStatus);
  1329. ASSERT(fResult);
  1330. // see what we have been asked for
  1331. if (PolicyValue == sipvAuto1)
  1332. {
  1333. fNeedServer = FALSE;
  1334. MinMemoryNeeded = 64 * 1024 * 1024; // 64MB of RAM
  1335. }
  1336. else
  1337. {
  1338. ASSERT (PolicyValue == sipvAuto2);
  1339. fNeedServer = TRUE;
  1340. MinMemoryNeeded = 127 * 1024 * 1024; // 127MB of RAM
  1341. }
  1342. // if we need server, but this is workstation, no state info
  1343. if (fNeedServer && (ProductType == NtProductWinNt))
  1344. {
  1345. g_fServerSideDebugInfoEnabled = FALSE;
  1346. return;
  1347. }
  1348. // if we have less physical memory than the one we need,
  1349. // no state info
  1350. if (MemoryStatus.ullTotalPhys < (ULONGLONG) MinMemoryNeeded)
  1351. {
  1352. g_fServerSideDebugInfoEnabled = FALSE;
  1353. return;
  1354. }
  1355. g_fServerSideDebugInfoEnabled = TRUE;
  1356. }
  1357. typedef enum tagExceptionListParserState
  1358. {
  1359. elpsOutsideOfQuotes,
  1360. elpsInsideQuotes,
  1361. elpsReadingWhitespace,
  1362. elpsReadingCharacter
  1363. } ExceptionListParserState;
  1364. BOOL
  1365. DoesThisProcessCmdLineStartWithThisString (
  1366. IN LPWSTR CmdLine,
  1367. IN LPWSTR CmdLineStart
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. Checks if the process name starts with the string given
  1372. in CmdLineStart
  1373. Arguments:
  1374. CmdLine - the process command line with path name stripped
  1375. CmdLineStart - the patter to match against
  1376. Return Value:
  1377. non-zero - there is a match
  1378. FALSE - there is no match
  1379. --*/
  1380. {
  1381. int CmdLineLength = RpcpStringLength(CmdLine);
  1382. int CmdLineStartLength = RpcpStringLength(CmdLineStart);
  1383. if (CmdLineLength >= CmdLineStartLength)
  1384. {
  1385. if (RpcpStringNCompare(CmdLine, CmdLineStart, CmdLineStartLength) == 0)
  1386. return TRUE;
  1387. }
  1388. return FALSE;
  1389. }
  1390. typedef enum tagExceptionListCharacterTypes
  1391. {
  1392. elctQuotes,
  1393. elctCharacter,
  1394. elctWhitespace
  1395. } ExceptionListCharacterTypes;
  1396. inline ExceptionListCharacterTypes
  1397. GetCharacterType (
  1398. RPC_CHAR Character
  1399. )
  1400. {
  1401. if (Character == '"')
  1402. return elctQuotes;
  1403. if (Character == ' ')
  1404. return elctWhitespace;
  1405. return elctCharacter;
  1406. }
  1407. RPC_STATUS
  1408. IsThisProcessAnException (
  1409. IN HKEY RegistryKey,
  1410. BOOL *fThisProcessIsException
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Checks whether the current process is in the exceptions list as
  1415. specified in the ExtErrorInfoExceptions registry key
  1416. Arguments:
  1417. RegistryKey - an open key to RPC_POLICY_SETTINGS
  1418. fThisProcessIsException - on output non-zero if this process is
  1419. an exception and FALSE otherwise
  1420. Return Value:
  1421. RPC_S_OK or RPC_S_* error
  1422. --*/
  1423. {
  1424. DWORD RegStatus;
  1425. RPC_CHAR *Buffer = NULL;
  1426. DWORD Type;
  1427. DWORD Size = 0;
  1428. int Retries = 5;
  1429. int State;
  1430. RPC_CHAR *CurrentPos;
  1431. RPC_CHAR *CurrentString;
  1432. RPC_CHAR *CommandLine;
  1433. RPC_CHAR *LastBackslash;
  1434. BOOL fIsSubstring;
  1435. *fThisProcessIsException = FALSE;
  1436. while (Retries > 0)
  1437. {
  1438. RegStatus = RegQueryValueExW(
  1439. RegistryKey,
  1440. L"ExtErrorInfoExceptions",
  1441. 0,
  1442. &Type,
  1443. (LPBYTE) Buffer,
  1444. &Size
  1445. );
  1446. if ( (RegStatus != ERROR_SUCCESS) && (RegStatus != ERROR_MORE_DATA) )
  1447. {
  1448. if (RegStatus == ERROR_FILE_NOT_FOUND)
  1449. RegStatus = RPC_S_OK;
  1450. else
  1451. RegStatus = RPC_S_OUT_OF_MEMORY;
  1452. goto CleanupAndReturn;
  1453. }
  1454. else
  1455. {
  1456. if ((Buffer == NULL) || (RegStatus == ERROR_MORE_DATA))
  1457. {
  1458. if (Buffer)
  1459. delete Buffer;
  1460. Buffer = new RPC_CHAR[Size];
  1461. if (Buffer == NULL)
  1462. {
  1463. RegStatus = RPC_S_OUT_OF_MEMORY;
  1464. goto CleanupAndReturn;
  1465. }
  1466. continue;
  1467. }
  1468. if (Type != REG_SZ)
  1469. {
  1470. RegStatus = RPC_S_INTERNAL_ERROR;
  1471. goto CleanupAndReturn;
  1472. }
  1473. ASSERT(RegStatus == RPC_S_OK);
  1474. CommandLine = GetCommandLine();
  1475. LastBackslash = wcsrchr(CommandLine, '\\');
  1476. if (LastBackslash != NULL)
  1477. CommandLine = LastBackslash + 1;
  1478. // here, Buffer contains the exception string
  1479. // The format of the exception string is:
  1480. // "cmd_line_start" "cmd_line_start" ...
  1481. // If there is only one cmd_line_start, it doesn't have to be in double quotes
  1482. State = elpsOutsideOfQuotes;
  1483. CurrentPos = Buffer;
  1484. CurrentString = NULL;
  1485. while (*CurrentPos != 0)
  1486. {
  1487. switch (State)
  1488. {
  1489. case elpsOutsideOfQuotes:
  1490. switch (GetCharacterType(*CurrentPos))
  1491. {
  1492. case elctQuotes:
  1493. CurrentString = CurrentPos;
  1494. State = elpsInsideQuotes;
  1495. break;
  1496. case elctCharacter:
  1497. CurrentString = CurrentPos;
  1498. State = elpsReadingCharacter;
  1499. break;
  1500. case elctWhitespace:
  1501. State = elpsReadingWhitespace;
  1502. break;
  1503. default:
  1504. ASSERT(0);
  1505. }
  1506. break;
  1507. case elpsReadingCharacter:
  1508. switch (GetCharacterType(*CurrentPos))
  1509. {
  1510. case elctQuotes:
  1511. *CurrentPos = 0;
  1512. fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
  1513. CommandLine, CurrentString);
  1514. if (fIsSubstring)
  1515. {
  1516. *fThisProcessIsException = TRUE;
  1517. goto CleanupAndReturn;
  1518. }
  1519. CurrentString = CurrentPos + 1;
  1520. State = elpsReadingCharacter;
  1521. break;
  1522. case elctWhitespace:
  1523. *CurrentPos = 0;
  1524. fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
  1525. CommandLine, CurrentString);
  1526. if (fIsSubstring)
  1527. {
  1528. *fThisProcessIsException = TRUE;
  1529. goto CleanupAndReturn;
  1530. }
  1531. State = elpsReadingCharacter;
  1532. break;
  1533. // default:
  1534. // can be elpsReadingCharacter
  1535. }
  1536. break;
  1537. case elpsReadingWhitespace:
  1538. switch (GetCharacterType(*CurrentPos))
  1539. {
  1540. case elctQuotes:
  1541. CurrentString = CurrentPos + 1;
  1542. State = elpsInsideQuotes;
  1543. break;
  1544. case elctCharacter:
  1545. CurrentString = CurrentPos;
  1546. State = elpsReadingCharacter;
  1547. break;
  1548. // default:
  1549. // can be elctWhitespace
  1550. }
  1551. break;
  1552. case elpsInsideQuotes:
  1553. switch (GetCharacterType(*CurrentPos))
  1554. {
  1555. case elctQuotes:
  1556. *CurrentPos = 0;
  1557. fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
  1558. CommandLine, CurrentString);
  1559. if (fIsSubstring)
  1560. {
  1561. *fThisProcessIsException = TRUE;
  1562. goto CleanupAndReturn;
  1563. }
  1564. State = elpsOutsideOfQuotes;
  1565. break;
  1566. //default:
  1567. // can be elctCharacter or elctWhitespace
  1568. }
  1569. break;
  1570. default:
  1571. ASSERT(0);
  1572. }
  1573. CurrentPos ++;
  1574. }
  1575. if (CurrentString)
  1576. {
  1577. fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
  1578. CommandLine, CurrentString);
  1579. if (fIsSubstring)
  1580. {
  1581. *fThisProcessIsException = TRUE;
  1582. goto CleanupAndReturn;
  1583. }
  1584. }
  1585. break;
  1586. }
  1587. Retries --;
  1588. }
  1589. CleanupAndReturn:
  1590. if (Buffer)
  1591. delete Buffer;
  1592. if (Retries == 0)
  1593. RegStatus = RPC_S_INTERNAL_ERROR;
  1594. return RegStatus;
  1595. }
  1596. RPC_STATUS ReadPolicySettings(void)
  1597. /*++
  1598. Routine Description:
  1599. Reads the policy settings for RPC and sets the appropriate global
  1600. variables.
  1601. Arguments:
  1602. void
  1603. Return Value:
  1604. RPC_S_OK or RPC_S_* error
  1605. --*/
  1606. {
  1607. HKEY RegistryKey;
  1608. DWORD RegStatus;
  1609. DWORD Result;
  1610. DWORD Type;
  1611. DWORD DwordSize = sizeof(DWORD);
  1612. BOOL ThisProcessIsException;
  1613. RegStatus = RegOpenKeyExW(
  1614. HKEY_LOCAL_MACHINE,
  1615. (LPWSTR) RPC_POLICY_SETTINGS,
  1616. 0L, //Reserved
  1617. KEY_READ,
  1618. &RegistryKey
  1619. );
  1620. if ( RegStatus != ERROR_SUCCESS )
  1621. {
  1622. if (RegStatus == ERROR_FILE_NOT_FOUND)
  1623. {
  1624. SetAutoPolicySettings(sipvAuto2);
  1625. return RPC_S_OK;
  1626. }
  1627. return RPC_S_OUT_OF_MEMORY;
  1628. }
  1629. RegStatus = RegQueryValueExW(
  1630. RegistryKey,
  1631. L"StateInformation",
  1632. 0,
  1633. &Type,
  1634. (LPBYTE) &Result,
  1635. &DwordSize
  1636. );
  1637. if ( RegStatus != ERROR_SUCCESS )
  1638. {
  1639. if (RegStatus == ERROR_FILE_NOT_FOUND)
  1640. {
  1641. SetAutoPolicySettings(sipvAuto2);
  1642. RegStatus = RPC_S_OK;
  1643. }
  1644. else
  1645. {
  1646. RegStatus = RPC_S_OUT_OF_MEMORY;
  1647. goto CleanupAndReturn;
  1648. }
  1649. }
  1650. else
  1651. {
  1652. if (Type != REG_DWORD)
  1653. {
  1654. RegStatus = RPC_S_INTERNAL_ERROR;
  1655. goto CleanupAndReturn;
  1656. }
  1657. ASSERT(RegStatus == RPC_S_OK);
  1658. switch (Result)
  1659. {
  1660. case sipvNone:
  1661. // nothing to do - the client/server DebugInfoEnabled values
  1662. // are off by default
  1663. break;
  1664. case sipvAuto1:
  1665. case sipvAuto2:
  1666. SetAutoPolicySettings((StateInformationPolicyValues)Result);
  1667. break;
  1668. case sipvServer:
  1669. g_fServerSideDebugInfoEnabled = TRUE;
  1670. break;
  1671. case sipvFull:
  1672. g_fServerSideDebugInfoEnabled = TRUE;
  1673. g_fClientSideDebugInfoEnabled = TRUE;
  1674. break;
  1675. default:
  1676. RegStatus = RPC_S_INTERNAL_ERROR;
  1677. goto CleanupAndReturn;
  1678. }
  1679. }
  1680. RegStatus = RegQueryValueExW(
  1681. RegistryKey,
  1682. L"ExtErrorInformation",
  1683. 0,
  1684. &Type,
  1685. (LPBYTE) &Result,
  1686. &DwordSize
  1687. );
  1688. if ( RegStatus != ERROR_SUCCESS )
  1689. {
  1690. if (RegStatus == ERROR_FILE_NOT_FOUND)
  1691. {
  1692. RegStatus = RPC_S_OK;
  1693. }
  1694. else
  1695. {
  1696. RegStatus = RPC_S_OUT_OF_MEMORY;
  1697. goto CleanupAndReturn;
  1698. }
  1699. }
  1700. else
  1701. {
  1702. if (Type != REG_DWORD)
  1703. {
  1704. RegStatus = RPC_S_INTERNAL_ERROR;
  1705. goto CleanupAndReturn;
  1706. }
  1707. ASSERT(RegStatus == RPC_S_OK);
  1708. switch (Result)
  1709. {
  1710. case eeipvOff:
  1711. // nothing to do - the g_fSendEEInfo is already false
  1712. break;
  1713. case eeipvOnWithExceptions:
  1714. RegStatus = IsThisProcessAnException(RegistryKey,
  1715. &ThisProcessIsException);
  1716. if ((RegStatus != RPC_S_OK) || (ThisProcessIsException == FALSE))
  1717. g_fSendEEInfo = TRUE;
  1718. break;
  1719. case eeipvOffWithExceptions:
  1720. RegStatus = IsThisProcessAnException(RegistryKey,
  1721. &ThisProcessIsException);
  1722. if ((RegStatus == RPC_S_OK) && (ThisProcessIsException == TRUE))
  1723. g_fSendEEInfo = TRUE;
  1724. break;
  1725. case eeipvOn:
  1726. g_fSendEEInfo = TRUE;
  1727. break;
  1728. default:
  1729. RegStatus = RPC_S_INTERNAL_ERROR;
  1730. goto CleanupAndReturn;
  1731. }
  1732. }
  1733. CleanupAndReturn:
  1734. RegCloseKey(RegistryKey);
  1735. return RegStatus;
  1736. }
  1737. RPCRTAPI
  1738. RPC_STATUS
  1739. RPC_ENTRY
  1740. I_RpcSystemFunction001 (
  1741. IN SystemFunction001Commands FunctionCode,
  1742. IN void *InData,
  1743. OUT void *OutData
  1744. )
  1745. /*++
  1746. Routine Description:
  1747. Test hook.
  1748. Arguments:
  1749. FunctionCode - which test function to perform
  1750. InData - input data from the test function
  1751. OutData - output data from the test function
  1752. Return Value:
  1753. RPC_S_OK or RPC_S_* error
  1754. --*/
  1755. {
  1756. THREAD *Thread;
  1757. InitializeIfNecessary();
  1758. Thread = ThreadSelf();
  1759. if (!Thread)
  1760. return RPC_S_OUT_OF_MEMORY;
  1761. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1762. switch (FunctionCode)
  1763. {
  1764. case sf001cHttpSetInChannelTarget:
  1765. case sf001cHttpSetOutChannelTarget:
  1766. return HTTP2TestHook (FunctionCode,
  1767. InData,
  1768. OutData
  1769. );
  1770. break;
  1771. default:
  1772. return RPC_S_CANNOT_SUPPORT;
  1773. }
  1774. return RPC_S_OK;
  1775. }
  1776. #ifdef WINNT35_UUIDS
  1777. unsigned long
  1778. SomeLongValue (
  1779. )
  1780. /*++
  1781. Routine Description:
  1782. This routine, SomeShortValue, AnotherShortValue, and SomeCharacterValue
  1783. are used to generate the fields of a GUID if we can not determine
  1784. the network address from the network card (so we can generate a
  1785. UUID). These routines must generate some pseudo random values
  1786. based on the current time and/or the time since boot as well as the
  1787. current process and thread.
  1788. For the long value, we will use the current thread identifier and
  1789. current process identifier bitwise exclusive ored together.
  1790. For the two short values, we use the low part of the time field
  1791. (which is long, which we split into two values).
  1792. Finally, for the character value, we use a constant.
  1793. Return Value:
  1794. An unsigned long value will be returned.
  1795. --*/
  1796. {
  1797. TEB * CurrentTeb;
  1798. CurrentTeb = NtCurrentTeb();
  1799. return(((unsigned long) CurrentTeb->ClientId.UniqueThread)
  1800. ^ ((unsigned long) CurrentTeb->ClientId.UniqueProcess));
  1801. }
  1802. unsigned short
  1803. SomeShortValue (
  1804. )
  1805. /*++
  1806. See SomeLongValue.
  1807. --*/
  1808. {
  1809. LARGE_INTEGER SystemTime;
  1810. for (;;)
  1811. {
  1812. NtQuerySystemTime(&SystemTime);
  1813. if (ThreadSelf()->TimeLow != SystemTime.LowPart)
  1814. break;
  1815. PauseExecution(1L);
  1816. }
  1817. ThreadSelf()->TimeLow = SystemTime.LowPart;
  1818. return((unsigned short) SystemTime.LowPart);
  1819. }
  1820. unsigned short
  1821. AnotherShortValue (
  1822. )
  1823. /*++
  1824. See SomeLongValue.
  1825. --*/
  1826. {
  1827. return((unsigned short) (ThreadSelf()->TimeLow >> 16));
  1828. }
  1829. unsigned char
  1830. SomeCharacterValue (
  1831. )
  1832. /*++
  1833. See SomeLongValue.
  1834. --*/
  1835. {
  1836. return(0x69);
  1837. }
  1838. #endif WINNT35_UUIDS
  1839. typedef struct {
  1840. RPC_STATUS RpcStatus;
  1841. long NtStatus;
  1842. } STATUS_MAPPING;
  1843. static const STATUS_MAPPING StatusMap[] =
  1844. {
  1845. { RPC_S_OK, STATUS_SUCCESS },
  1846. { RPC_S_INVALID_STRING_BINDING, RPC_NT_INVALID_STRING_BINDING },
  1847. { RPC_S_WRONG_KIND_OF_BINDING, RPC_NT_WRONG_KIND_OF_BINDING },
  1848. { RPC_S_INVALID_BINDING, RPC_NT_INVALID_BINDING },
  1849. { RPC_S_PROTSEQ_NOT_SUPPORTED, RPC_NT_PROTSEQ_NOT_SUPPORTED },
  1850. { RPC_S_INVALID_RPC_PROTSEQ, RPC_NT_INVALID_RPC_PROTSEQ },
  1851. { RPC_S_INVALID_STRING_UUID, RPC_NT_INVALID_STRING_UUID },
  1852. { RPC_S_INVALID_ENDPOINT_FORMAT, RPC_NT_INVALID_ENDPOINT_FORMAT },
  1853. { RPC_S_INVALID_NET_ADDR, RPC_NT_INVALID_NET_ADDR },
  1854. { RPC_S_NO_ENDPOINT_FOUND, RPC_NT_NO_ENDPOINT_FOUND },
  1855. { RPC_S_INVALID_TIMEOUT, RPC_NT_INVALID_TIMEOUT },
  1856. { RPC_S_OBJECT_NOT_FOUND, RPC_NT_OBJECT_NOT_FOUND },
  1857. { RPC_S_ALREADY_REGISTERED, RPC_NT_ALREADY_REGISTERED },
  1858. { RPC_S_TYPE_ALREADY_REGISTERED, RPC_NT_TYPE_ALREADY_REGISTERED },
  1859. { RPC_S_ALREADY_LISTENING, RPC_NT_ALREADY_LISTENING },
  1860. { RPC_S_NO_PROTSEQS_REGISTERED, RPC_NT_NO_PROTSEQS_REGISTERED },
  1861. { RPC_S_NOT_LISTENING, RPC_NT_NOT_LISTENING },
  1862. { RPC_S_UNKNOWN_MGR_TYPE, RPC_NT_UNKNOWN_MGR_TYPE },
  1863. { RPC_S_UNKNOWN_IF, RPC_NT_UNKNOWN_IF },
  1864. { RPC_S_NO_BINDINGS, RPC_NT_NO_BINDINGS },
  1865. { RPC_S_NO_MORE_BINDINGS, RPC_NT_NO_MORE_BINDINGS },
  1866. { RPC_S_NO_PROTSEQS, RPC_NT_NO_PROTSEQS },
  1867. { RPC_S_CANT_CREATE_ENDPOINT, RPC_NT_CANT_CREATE_ENDPOINT },
  1868. { RPC_S_OUT_OF_RESOURCES, RPC_NT_OUT_OF_RESOURCES },
  1869. { RPC_S_SERVER_UNAVAILABLE, RPC_NT_SERVER_UNAVAILABLE },
  1870. { RPC_S_SERVER_TOO_BUSY, RPC_NT_SERVER_TOO_BUSY },
  1871. { RPC_S_INVALID_NETWORK_OPTIONS, RPC_NT_INVALID_NETWORK_OPTIONS },
  1872. { RPC_S_NO_CALL_ACTIVE, RPC_NT_NO_CALL_ACTIVE },
  1873. { RPC_S_CALL_FAILED, RPC_NT_CALL_FAILED },
  1874. { RPC_S_CALL_CANCELLED, RPC_NT_CALL_CANCELLED },
  1875. { RPC_S_CALL_FAILED_DNE, RPC_NT_CALL_FAILED_DNE },
  1876. { RPC_S_PROTOCOL_ERROR, RPC_NT_PROTOCOL_ERROR },
  1877. { RPC_S_UNSUPPORTED_TRANS_SYN, RPC_NT_UNSUPPORTED_TRANS_SYN },
  1878. { RPC_S_SERVER_OUT_OF_MEMORY, STATUS_INSUFF_SERVER_RESOURCES },
  1879. { RPC_S_UNSUPPORTED_TYPE, RPC_NT_UNSUPPORTED_TYPE },
  1880. { RPC_S_INVALID_TAG, RPC_NT_INVALID_TAG },
  1881. { RPC_S_INVALID_BOUND, RPC_NT_INVALID_BOUND },
  1882. { RPC_S_NO_ENTRY_NAME, RPC_NT_NO_ENTRY_NAME },
  1883. { RPC_S_INVALID_NAME_SYNTAX, RPC_NT_INVALID_NAME_SYNTAX },
  1884. { RPC_S_UNSUPPORTED_NAME_SYNTAX, RPC_NT_UNSUPPORTED_NAME_SYNTAX },
  1885. { RPC_S_UUID_NO_ADDRESS, RPC_NT_UUID_NO_ADDRESS },
  1886. { RPC_S_DUPLICATE_ENDPOINT, RPC_NT_DUPLICATE_ENDPOINT },
  1887. { RPC_S_UNKNOWN_AUTHN_TYPE, RPC_NT_UNKNOWN_AUTHN_TYPE },
  1888. { RPC_S_MAX_CALLS_TOO_SMALL, RPC_NT_MAX_CALLS_TOO_SMALL },
  1889. { RPC_S_STRING_TOO_LONG, RPC_NT_STRING_TOO_LONG },
  1890. { RPC_S_PROTSEQ_NOT_FOUND, RPC_NT_PROTSEQ_NOT_FOUND },
  1891. { RPC_S_PROCNUM_OUT_OF_RANGE, RPC_NT_PROCNUM_OUT_OF_RANGE },
  1892. { RPC_S_BINDING_HAS_NO_AUTH, RPC_NT_BINDING_HAS_NO_AUTH },
  1893. { RPC_S_UNKNOWN_AUTHN_SERVICE, RPC_NT_UNKNOWN_AUTHN_SERVICE },
  1894. { RPC_S_UNKNOWN_AUTHN_LEVEL, RPC_NT_UNKNOWN_AUTHN_LEVEL },
  1895. { RPC_S_INVALID_AUTH_IDENTITY, RPC_NT_INVALID_AUTH_IDENTITY },
  1896. { RPC_S_UNKNOWN_AUTHZ_SERVICE, RPC_NT_UNKNOWN_AUTHZ_SERVICE },
  1897. { EPT_S_INVALID_ENTRY, EPT_NT_INVALID_ENTRY },
  1898. { EPT_S_CANT_PERFORM_OP, EPT_NT_CANT_PERFORM_OP },
  1899. { EPT_S_NOT_REGISTERED, EPT_NT_NOT_REGISTERED },
  1900. { RPC_S_NOTHING_TO_EXPORT, RPC_NT_NOTHING_TO_EXPORT },
  1901. { RPC_S_INCOMPLETE_NAME, RPC_NT_INCOMPLETE_NAME },
  1902. { RPC_S_INVALID_VERS_OPTION, RPC_NT_INVALID_VERS_OPTION },
  1903. { RPC_S_NO_MORE_MEMBERS, RPC_NT_NO_MORE_MEMBERS },
  1904. { RPC_S_NOT_ALL_OBJS_UNEXPORTED, RPC_NT_NOT_ALL_OBJS_UNEXPORTED },
  1905. { RPC_S_INTERFACE_NOT_FOUND, RPC_NT_INTERFACE_NOT_FOUND },
  1906. { RPC_S_ENTRY_ALREADY_EXISTS, RPC_NT_ENTRY_ALREADY_EXISTS },
  1907. { RPC_S_ENTRY_NOT_FOUND, RPC_NT_ENTRY_NOT_FOUND },
  1908. { RPC_S_NAME_SERVICE_UNAVAILABLE, RPC_NT_NAME_SERVICE_UNAVAILABLE },
  1909. { RPC_S_INVALID_NAF_ID, RPC_NT_INVALID_NAF_ID },
  1910. { RPC_S_CANNOT_SUPPORT, RPC_NT_CANNOT_SUPPORT },
  1911. { RPC_S_NO_CONTEXT_AVAILABLE, RPC_NT_NO_CONTEXT_AVAILABLE },
  1912. { RPC_S_INTERNAL_ERROR, RPC_NT_INTERNAL_ERROR },
  1913. { RPC_S_ZERO_DIVIDE, RPC_NT_ZERO_DIVIDE },
  1914. { RPC_S_ADDRESS_ERROR, RPC_NT_ADDRESS_ERROR },
  1915. { RPC_S_FP_DIV_ZERO, RPC_NT_FP_DIV_ZERO },
  1916. { RPC_S_FP_UNDERFLOW, RPC_NT_FP_UNDERFLOW },
  1917. { RPC_S_FP_OVERFLOW, RPC_NT_FP_OVERFLOW },
  1918. { RPC_X_NO_MORE_ENTRIES, RPC_NT_NO_MORE_ENTRIES },
  1919. { RPC_X_SS_CHAR_TRANS_OPEN_FAIL, RPC_NT_SS_CHAR_TRANS_OPEN_FAIL },
  1920. { RPC_X_SS_CHAR_TRANS_SHORT_FILE, RPC_NT_SS_CHAR_TRANS_SHORT_FILE },
  1921. { RPC_X_SS_IN_NULL_CONTEXT, RPC_NT_SS_IN_NULL_CONTEXT },
  1922. { RPC_X_SS_CONTEXT_MISMATCH, RPC_NT_SS_CONTEXT_MISMATCH },
  1923. { RPC_X_SS_CONTEXT_DAMAGED, RPC_NT_SS_CONTEXT_DAMAGED },
  1924. { RPC_X_SS_HANDLES_MISMATCH, RPC_NT_SS_HANDLES_MISMATCH },
  1925. { RPC_X_SS_CANNOT_GET_CALL_HANDLE, RPC_NT_SS_CANNOT_GET_CALL_HANDLE },
  1926. { RPC_X_NULL_REF_POINTER, RPC_NT_NULL_REF_POINTER },
  1927. { RPC_X_ENUM_VALUE_OUT_OF_RANGE, RPC_NT_ENUM_VALUE_OUT_OF_RANGE },
  1928. { RPC_X_BYTE_COUNT_TOO_SMALL, RPC_NT_BYTE_COUNT_TOO_SMALL },
  1929. { RPC_X_BAD_STUB_DATA, RPC_NT_BAD_STUB_DATA },
  1930. { ERROR_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
  1931. { ERROR_OUTOFMEMORY, STATUS_NO_MEMORY },
  1932. { ERROR_MAX_THRDS_REACHED, STATUS_NO_MEMORY },
  1933. { ERROR_INSUFFICIENT_BUFFER, STATUS_BUFFER_TOO_SMALL },
  1934. { ERROR_INVALID_SECURITY_DESCR, STATUS_INVALID_SECURITY_DESCR },
  1935. { ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED },
  1936. { ERROR_NOACCESS, STATUS_ACCESS_VIOLATION },
  1937. { RPC_S_CALL_IN_PROGRESS, RPC_NT_CALL_IN_PROGRESS },
  1938. { RPC_S_GROUP_MEMBER_NOT_FOUND, RPC_NT_GROUP_MEMBER_NOT_FOUND },
  1939. { EPT_S_CANT_CREATE, EPT_NT_CANT_CREATE },
  1940. { RPC_S_INVALID_OBJECT, RPC_NT_INVALID_OBJECT },
  1941. { RPC_S_INVALID_ASYNC_HANDLE, RPC_NT_INVALID_ASYNC_HANDLE },
  1942. { RPC_S_INVALID_ASYNC_CALL, RPC_NT_INVALID_ASYNC_CALL },
  1943. { RPC_X_PIPE_CLOSED, RPC_NT_PIPE_CLOSED },
  1944. { RPC_X_PIPE_EMPTY, RPC_NT_PIPE_EMPTY },
  1945. { RPC_X_PIPE_DISCIPLINE_ERROR, RPC_NT_PIPE_DISCIPLINE_ERROR }
  1946. };
  1947. long RPC_ENTRY
  1948. I_RpcMapWin32Status (
  1949. IN RPC_STATUS Status
  1950. )
  1951. /*++
  1952. Routine Description:
  1953. This routine maps a WIN32 RPC status code into an NT RPC status code.
  1954. Arguments:
  1955. Status - Supplies the WIN32 RPC status code to be mapped.
  1956. Return Value:
  1957. The NT RPC status code corresponding to the WIN32 RPC status code
  1958. will be returned.
  1959. --*/
  1960. {
  1961. register int i;
  1962. for(i = 0; i < sizeof(StatusMap)/sizeof(STATUS_MAPPING); i++)
  1963. {
  1964. if (StatusMap[i].RpcStatus == Status)
  1965. {
  1966. return(StatusMap[i].NtStatus);
  1967. }
  1968. }
  1969. return(Status);
  1970. }