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.

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