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.

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