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.

493 lines
13 KiB

  1. //============================================================================
  2. // Copyright (c) 1996, Microsoft Corporation
  3. //
  4. // File: setup.c
  5. //
  6. // History:
  7. // 06/24/96 Abolade Gbadegesin Created.
  8. //
  9. // Implements API functions used by IP and IPX to read installation information
  10. // stored under HKLM\Software\Microsoft\Router.
  11. //
  12. // The API functions are presented first, followed by private functions
  13. // in alphabetical order.
  14. //============================================================================
  15. #define UNICODE
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <rtutils.h>
  21. //#define STRSAFE_LIB
  22. #include <strsafe.h>
  23. //
  24. // Constant strings used to access the registry:
  25. //
  26. const WCHAR c_szDLLName[] = L"DLLName";
  27. const WCHAR c_szMicrosoft[] = L"Microsoft";
  28. const WCHAR c_szProtocolId[] = L"ProtocolId";
  29. const WCHAR c_szRouter[] = L"Router";
  30. const TCHAR c_szCurrentVersion[] = L"CurrentVersion";
  31. const WCHAR c_szRouterManagers[] = L"RouterManagers";
  32. const WCHAR c_szSoftware[] = L"Software";
  33. //
  34. // Memory management macros:
  35. //
  36. #define Malloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
  37. #define ReAlloc(p,s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
  38. #define Free(p) HeapFree(GetProcessHeap(), 0, (p))
  39. #define Free0(p) ((p) ? Free(p) : TRUE)
  40. DWORD
  41. QueryRmSoftwareKey(
  42. IN HKEY hkeyMachine,
  43. IN DWORD dwTransportId,
  44. OUT HKEY* phkrm,
  45. OUT LPWSTR* lplpwsRm
  46. );
  47. //----------------------------------------------------------------------------
  48. // Function: MprSetupProtocolEnum
  49. //
  50. // Enumerates the protocols installed for transport 'dwTransportId'.
  51. //
  52. // The information is loaded from HKLM\Software\Microsoft\Router,
  53. // where subkeys exist for each router-manager under the 'RouterManagers' key.
  54. // Each router-manager subkey has subkeys containing information
  55. // about that router-manager's routing-protocols.
  56. //
  57. // This API reads a subset of that information, so that router-managers
  58. // can map protocol-IDs to DLL names when loading routing-protocols.
  59. //----------------------------------------------------------------------------
  60. DWORD APIENTRY
  61. MprSetupProtocolEnum(
  62. IN DWORD dwTransportId,
  63. OUT LPBYTE* lplpBuffer, // MPR_PROTOCOL_0
  64. OUT LPDWORD lpdwEntriesRead
  65. ) {
  66. HKEY hkrm;
  67. WCHAR* lpwsRm = NULL;
  68. DWORD dwErr, dwItemCount;
  69. MPR_PROTOCOL_0* pItem, *pItemTable = NULL;
  70. HRESULT hrResult;
  71. //
  72. // Validate the caller's parameters
  73. //
  74. if (!lplpBuffer ||
  75. !lpdwEntriesRead) { return ERROR_INVALID_PARAMETER; }
  76. *lplpBuffer = NULL;
  77. *lpdwEntriesRead = 0;
  78. //
  79. // Open the key for the specified router-manager
  80. // under HKLM\Software\Microsoft\Router\CurrentVersion\RouterManagers
  81. //
  82. dwErr = QueryRmSoftwareKey(
  83. HKEY_LOCAL_MACHINE, dwTransportId, &hkrm, &lpwsRm
  84. );
  85. if (dwErr != NO_ERROR) { return dwErr; }
  86. //
  87. // The transport was found, so its registry key is in 'hkrm'
  88. //
  89. do {
  90. //
  91. // Retrieve information about the subkeys of the router-manager,
  92. // since these should all contain data for routing-protocols.
  93. //
  94. WCHAR* pwsKey;
  95. DWORD i, dwSize, dwType;
  96. DWORD dwKeyCount, dwMaxKeyLength/*length in tchars*/;
  97. dwErr = RegQueryInfoKey(//sssafe
  98. hkrm, NULL, NULL, NULL, &dwKeyCount,
  99. &dwMaxKeyLength,//length in tchars
  100. NULL, NULL, NULL, NULL, NULL, NULL
  101. );
  102. if (dwErr != ERROR_SUCCESS) { break; }
  103. //
  104. // Allocate enough space for the longest of the subkeys
  105. //
  106. pwsKey = Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  107. if (!pwsKey) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  108. //
  109. // Allocate an array to hold the keys' contents
  110. //
  111. pItemTable = (MPR_PROTOCOL_0*)Malloc(dwKeyCount * sizeof(*pItem));
  112. if (!pItemTable) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  113. ZeroMemory(pItemTable, dwKeyCount * sizeof(*pItem));
  114. //
  115. // Enumerate the keys
  116. //
  117. dwItemCount = 0;
  118. for (i = 0; i < dwKeyCount; i++) {
  119. HKEY hkprot;
  120. PBYTE pValue = NULL;
  121. //
  122. // Get the name of the current key
  123. //
  124. dwSize = dwMaxKeyLength + 1;//num tchars
  125. dwErr = RegEnumKeyEx( //sssafe
  126. hkrm, i, pwsKey, &dwSize, NULL, NULL, NULL, NULL
  127. );
  128. if (dwErr != ERROR_SUCCESS) { continue; }
  129. //
  130. // Open the key
  131. //
  132. dwErr = RegOpenKeyEx(hkrm, pwsKey, 0, KEY_READ, &hkprot);
  133. if (dwErr != ERROR_SUCCESS) { continue; }
  134. pItem = pItemTable + dwItemCount;
  135. do {
  136. DWORD dwMaxValLength;
  137. //
  138. // Copy the string for the protocol
  139. //
  140. hrResult = StringCchCopy(pItem->wszProtocol,
  141. RTUTILS_MAX_PROTOCOL_NAME_LEN+1, pwsKey);
  142. if (FAILED(hrResult))
  143. {
  144. dwErr = HRESULT_CODE(hrResult);
  145. break;
  146. }
  147. //
  148. // Get information about the key's values
  149. //
  150. dwErr = RegQueryInfoKey(//sssafe
  151. hkprot, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  152. NULL, &dwMaxValLength,//length in tchars
  153. NULL, NULL
  154. );
  155. if (dwErr != ERROR_SUCCESS) { break; }
  156. //
  157. // Allocate space to hold the longest of the values
  158. //
  159. pValue = (PBYTE) Malloc((dwMaxValLength + 1)* sizeof(WCHAR));
  160. if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  161. //
  162. // Read the ProtocolId value
  163. //
  164. dwSize = (dwMaxValLength + 1)* sizeof(WCHAR);//size in bytes
  165. dwErr = RegQueryValueEx(
  166. hkprot, c_szProtocolId, 0, &dwType, pValue, &dwSize
  167. );
  168. if (dwErr != ERROR_SUCCESS) { break; }
  169. if (dwType!=REG_DWORD) {
  170. dwErr = ERROR_INVALID_DATA;
  171. break;
  172. }
  173. pItem->dwProtocolId = *(PDWORD)pValue;
  174. //
  175. // Read the DLLName value
  176. //
  177. dwSize = (dwMaxValLength + 1)* sizeof(WCHAR);//size in bytes
  178. dwErr = RegQueryValueEx(
  179. hkprot, c_szDLLName, 0, &dwType, pValue, &dwSize
  180. );
  181. if (dwErr != ERROR_SUCCESS) { break; }
  182. if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
  183. {
  184. dwErr = ERROR_INVALID_DATA;
  185. break;
  186. }
  187. hrResult = StringCchCopy(pItem->wszDLLName,
  188. RTUTILS_MAX_PROTOCOL_DLL_LEN+1,
  189. (WCHAR*)pValue);
  190. if (FAILED(hrResult))
  191. {
  192. dwErr = HRESULT_CODE(hrResult);
  193. break;
  194. }
  195. //
  196. // Increment the count of loaded protocols
  197. //
  198. ++dwItemCount;
  199. dwErr = ERROR_SUCCESS;
  200. } while(FALSE);
  201. Free0(pValue);
  202. RegCloseKey(hkprot);
  203. }
  204. Free0(pwsKey);
  205. } while(FALSE);
  206. Free0(lpwsRm);
  207. if (dwErr != NO_ERROR) {
  208. Free0(pItemTable);
  209. }
  210. else {
  211. //
  212. // Adjust the size of the buffer to be returned,
  213. // in case not all the keys contained routing-protocols,
  214. // and save the number of protocols loaded.
  215. //
  216. {
  217. *lplpBuffer = ReAlloc(pItemTable, dwItemCount * sizeof(*pItem));
  218. if (!*lplpBuffer)
  219. {
  220. Free0(pItemTable);
  221. RegCloseKey(hkrm);
  222. return ERROR_NOT_ENOUGH_MEMORY;
  223. }
  224. }
  225. *lpdwEntriesRead = dwItemCount;
  226. }
  227. RegCloseKey(hkrm);
  228. return dwErr;
  229. }
  230. //----------------------------------------------------------------------------
  231. // Function: MprSetupProtocolFree
  232. //
  233. // Called to free a buffer allocated by 'MprSetupProtocolEnum'.
  234. //----------------------------------------------------------------------------
  235. DWORD APIENTRY
  236. MprSetupProtocolFree(
  237. IN LPVOID lpBuffer
  238. ) {
  239. if (!lpBuffer) { return ERROR_INVALID_PARAMETER; }
  240. Free(lpBuffer);
  241. return NO_ERROR;
  242. }
  243. //----------------------------------------------------------------------------
  244. // Function: QueryRmSoftwareKey
  245. //
  246. // Called to open the key for a router-manager given its transport ID.
  247. //----------------------------------------------------------------------------
  248. DWORD
  249. QueryRmSoftwareKey(
  250. IN HKEY hkeyMachine,
  251. IN DWORD dwTransportId,
  252. OUT HKEY* phkrm,
  253. OUT LPWSTR* lplpwsRm
  254. ) {
  255. HKEY hkey;
  256. DWORD dwErr=ERROR_SUCCESS;
  257. WCHAR wszKey[256], *pwsKey;
  258. HRESULT hrResult;
  259. *lplpwsRm = NULL;
  260. //
  261. // Open the key HKLM\Software\Microsoft\Router\RouterManagers
  262. //
  263. hrResult = StringCchPrintf(
  264. wszKey, 256, L"%s\\%s\\%s\\%s\\%s",
  265. c_szSoftware, c_szMicrosoft, c_szRouter,
  266. c_szCurrentVersion, c_szRouterManagers
  267. );
  268. if (FAILED(hrResult))
  269. return HRESULT_CODE(hrResult);
  270. dwErr = RegOpenKeyEx(hkeyMachine, wszKey, 0, KEY_READ, &hkey);
  271. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  272. //
  273. // Enumerate the subkeys of the 'RouterManagers' key,
  274. // in search of one which as a 'ProtocolId' value equal to 'dwTransportId'.
  275. //
  276. do {
  277. //
  278. // Retrieve information about the subkeys of the key
  279. //
  280. DWORD dwKeyCount, dwMaxKeyLength;
  281. DWORD i, dwSize, dwType, dwProtocolId = ~dwTransportId;
  282. dwErr = RegQueryInfoKey(//sssafe
  283. hkey, NULL, NULL, NULL, &dwKeyCount,
  284. &dwMaxKeyLength, //length in tchars
  285. NULL, NULL, NULL, NULL, NULL, NULL
  286. );
  287. if (dwErr != ERROR_SUCCESS) { break; }
  288. //
  289. // Allocate enough space for the longest of the subkeys
  290. //
  291. pwsKey = Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  292. if (!pwsKey) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  293. //
  294. // Enumerate the keys
  295. //
  296. for (i = 0; i < dwKeyCount; i++) {
  297. //
  298. // Get the name of the current key
  299. //
  300. dwSize = dwMaxKeyLength + 1;//num tchars
  301. dwErr = RegEnumKeyEx(//sssafe
  302. hkey, i, pwsKey, &dwSize, NULL, NULL, NULL, NULL
  303. );
  304. if (dwErr != ERROR_SUCCESS) { continue; }
  305. //
  306. // Open the key
  307. //
  308. dwErr = RegOpenKeyEx(hkey, pwsKey, 0, KEY_READ, phkrm);
  309. if (dwErr != ERROR_SUCCESS) { continue; }
  310. //
  311. // Try to read the ProtocolId value
  312. //
  313. dwSize = sizeof(dwProtocolId);
  314. dwErr = RegQueryValueEx(
  315. *phkrm, c_szProtocolId, 0, &dwType,
  316. (BYTE*)&dwProtocolId, &dwSize
  317. );
  318. if (dwType != REG_DWORD)
  319. {
  320. RegCloseKey(*phkrm);
  321. dwErr = ERROR_INVALID_DATA;
  322. break;
  323. }
  324. //
  325. // Break if this is the transport we're looking for,
  326. // otherwise close the key and continue
  327. //
  328. if (dwErr == ERROR_SUCCESS &&
  329. dwProtocolId == dwTransportId) { break; }
  330. RegCloseKey(*phkrm);
  331. }
  332. if (i >= dwKeyCount) { Free(pwsKey); break; }
  333. //
  334. // The transport was found, so save its key-name
  335. //
  336. if (dwErr == ERROR_SUCCESS)
  337. *lplpwsRm = pwsKey;
  338. } while(FALSE);
  339. RegCloseKey(hkey);
  340. return (*lplpwsRm ? NO_ERROR :
  341. (dwErr==ERROR_SUCCESS)? ERROR_NO_MORE_ITEMS:dwErr);
  342. }