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.

6370 lines
159 KiB

  1. //============================================================================
  2. // Copyright (c) 1996, Microsoft Corporation.
  3. //
  4. // File: rtcfg.c
  5. //
  6. // History:
  7. // 5/4/96 Abolade-Gbadegesin Created.
  8. //
  9. // Contains implementation of functions which provide access
  10. // to the persistent store of configuration for the router-servoce.
  11. // Currently, the router-configuration is stored in the registry.
  12. //
  13. // The implementations of the APIs are presented first,
  14. // followed by the private utility functions in alphabetical order.
  15. //
  16. // N.B.!!!!!!:
  17. // When modifying this file, respect its coding conventions and organization.
  18. // * maintain the alphabetical ordering of the routines.
  19. // * remain within 80 characters per line
  20. // * indent in steps of 4 spaces
  21. // * all conditional-blocks should be within braces (even single statements)
  22. // * SLM doesn't charge by the byte; use whitespace and comments liberally,
  23. // and use long, thoroughly-descriptive names.
  24. // * try to rely on Win32 routines (e.g. lstrcmpi, WideCharToMultiByte, etc.).
  25. // Any code which uses a different style (whatever its merits) should be put
  26. // in a different file.
  27. //============================================================================
  28. #include <nt.h>
  29. #include <ntrtl.h>
  30. #include <nturtl.h>
  31. #include <windows.h>
  32. #include <dim.h>
  33. #include <mprapi.h>
  34. #include <mprapip.h>
  35. #include <mprerror.h>
  36. #include "rtcfg.h"
  37. #include "guidmap.h"
  38. #include "hashtab.h"
  39. //
  40. // Locks down the mprconfig api's.
  41. //
  42. CRITICAL_SECTION CfgLock;
  43. #define AcquireMprConfigLock() EnterCriticalSection(&CfgLock)
  44. #define ReleaseMprConfigLock() LeaveCriticalSection(&CfgLock)
  45. //
  46. // Hash table of server CB's
  47. //
  48. HANDLE g_htabServers = NULL;
  49. #define SERVERCB_HASH_SIZE 13
  50. //
  51. // Server structure signiture (27902)
  52. //
  53. #define SERVERCB_SIG 0x0000cfcb
  54. //
  55. // Local static strings, *in alphabetical order*.
  56. //
  57. const WCHAR c_szConfigVersion[] = L"ConfigVersion";
  58. const WCHAR c_szCurrentBuildNumber[] = L"CurrentBuildNumber";
  59. const WCHAR c_szDLLPath[] = L"DLLPath";
  60. const WCHAR c_szDialoutHours[] = L"DialoutHours";
  61. const WCHAR c_szEmpty[] = L"";
  62. const CHAR c_szEmptyA[] = "";
  63. const WCHAR c_szEnabled[] = L"Enabled";
  64. const WCHAR c_szFilterSets[] = L"FilterSets";
  65. const WCHAR c_szGlobalInFilter[] = L"GlobalInFilter";
  66. const WCHAR c_szGlobalInfo[] = L"GlobalInfo";
  67. const WCHAR c_szGlobalInterfaceInfo[] = L"GlobalInterfaceInfo";
  68. const WCHAR c_szGlobalOutFilter[] = L"GlobalOutFilter";
  69. const WCHAR c_szInFilterInfo[] = L"InFilterInfo";
  70. const WCHAR c_szInterfaceInfo[] = L"InterfaceInfo";
  71. const WCHAR c_szInterfaceName[] = L"InterfaceName";
  72. const WCHAR c_szInterfaces[] = L"Interfaces";
  73. const WCHAR c_szIP[] = L"IP";
  74. const WCHAR c_szIPX[] = L"IPX";
  75. const WCHAR c_szMpr[] = L".mpr";
  76. const CHAR c_szMprConfigA[] = "MprConfig";
  77. const WCHAR c_szNullFilter[] = L"NullFilter";
  78. const WCHAR c_szNt40BuildNumber[] = L"1381";
  79. const WCHAR c_szOutFilterInfo[] = L"OutFilterInfo";
  80. const WCHAR c_szParameters[] = L"Parameters";
  81. const WCHAR c_szPhonebook[] = L"Phonebook";
  82. const WCHAR c_szProtocolId[] = L"ProtocolId";
  83. const WCHAR c_szRemoteAccess[] = L"RemoteAccess";
  84. const WCHAR c_szRouter[] = L"Router";
  85. const WCHAR c_szRouterManagers[] = L"RouterManagers";
  86. const WCHAR c_szRouterPbkPath[] =
  87. L"\\ADMIN$\\System32\\RAS\\Router.pbk";
  88. const WCHAR c_szRouterType[] = L"RouterType";
  89. const WCHAR c_szRemoteSys32[] = L"\\ADMIN$\\System32\\";
  90. const WCHAR c_szStamp[] = L"Stamp";
  91. const WCHAR c_szSystemCCSServices[] =
  92. L"System\\CurrentControlSet\\Services";
  93. const WCHAR c_szType[] = L"Type";
  94. const WCHAR c_szUncPrefix[] = L"\\\\";
  95. const WCHAR c_szWinVersionPath[] =
  96. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
  97. //
  98. // Defines call back function type for EnumLanInterfaces below
  99. //
  100. typedef DWORD
  101. (*PENUMIFCALLBACKFUNC)(
  102. SERVERCB*,
  103. HKEY,
  104. DWORD
  105. );
  106. typedef
  107. HRESULT
  108. (APIENTRY* PINSTALLSERVERFUNC)();
  109. //
  110. // Local prototypes
  111. //
  112. DWORD
  113. FormatServerNameForMprCfgApis(
  114. IN PWCHAR pszServer,
  115. OUT PWCHAR* ppszServer);
  116. DWORD
  117. ServerCbAdd(
  118. IN SERVERCB* pserver);
  119. int
  120. ServerCbCompare(
  121. IN HANDLE hKey,
  122. IN HANDLE hData);
  123. DWORD
  124. ServerCbDelete(
  125. IN SERVERCB* pserver);
  126. DWORD
  127. ServerCbFind(
  128. IN PWCHAR pszServer,
  129. OUT SERVERCB** ppServerCB);
  130. ULONG
  131. ServerCbHash(
  132. IN HANDLE hData);
  133. #define MprConfigServerValidateCb(_x) \
  134. (((_x) && ((_x)->dwSigniture == SERVERCB_SIG)) ? NO_ERROR : ERROR_INVALID_PARAMETER)
  135. //----------------------------------------------------------------------------
  136. // Function: MprConfigServerInstall
  137. //
  138. // Presets any configuration values needed before starting the router service.
  139. //----------------------------------------------------------------------------
  140. DWORD APIENTRY
  141. MprConfigServerInstall(
  142. IN DWORD dwLevel,
  143. IN PVOID pBuffer)
  144. {
  145. HRESULT hr = S_OK;
  146. DWORD dwErr = NO_ERROR;
  147. HINSTANCE hLib = NULL;
  148. PINSTALLSERVERFUNC pInstall = NULL;
  149. if ((dwLevel != 0) || (pBuffer != NULL))
  150. {
  151. return ERROR_INVALID_PARAMETER;
  152. }
  153. do
  154. {
  155. hLib = LoadLibraryW(L"mprsnap.dll");
  156. if (hLib == NULL)
  157. {
  158. dwErr = GetLastError();
  159. break;
  160. }
  161. pInstall = (PINSTALLSERVERFUNC)
  162. GetProcAddress(hLib, "MprConfigServerInstallPrivate");
  163. if (pInstall == NULL)
  164. {
  165. dwErr = ERROR_CAN_NOT_COMPLETE;
  166. break;
  167. }
  168. hr = pInstall();
  169. dwErr = (HRESULT_FACILITY(hr) == FACILITY_WIN32) ?
  170. HRESULT_CODE(hr) :
  171. hr;
  172. } while (FALSE);
  173. // Cleanup
  174. //
  175. {
  176. if (hLib)
  177. {
  178. FreeLibrary(hLib);
  179. }
  180. }
  181. return dwErr;
  182. }
  183. //----------------------------------------------------------------------------
  184. // Function: MprConfigServerConnect
  185. //
  186. // Connects to the store for the router-service on 'lpwsServerName'.
  187. //----------------------------------------------------------------------------
  188. DWORD APIENTRY
  189. MprConfigServerConnect(
  190. IN LPWSTR lpwsServerName,
  191. OUT HANDLE* phMprConfig
  192. )
  193. {
  194. DWORD dwErr;
  195. SERVERCB* pserver = NULL;
  196. PWCHAR pszServerNameFmt = NULL;
  197. // Validate and initialzie
  198. //
  199. if (!phMprConfig) { return ERROR_INVALID_PARAMETER; }
  200. *phMprConfig = NULL;
  201. dwErr = FormatServerNameForMprCfgApis(
  202. lpwsServerName,
  203. &pszServerNameFmt);
  204. if (dwErr != NO_ERROR) { return dwErr; }
  205. // Get the lock
  206. //
  207. AcquireMprConfigLock();
  208. do {
  209. //
  210. // See if a handle to the given server is already available
  211. //
  212. dwErr = ServerCbFind(pszServerNameFmt, &pserver);
  213. if (dwErr == NO_ERROR)
  214. {
  215. pserver->dwRefCount++;
  216. *phMprConfig = (HANDLE)pserver;
  217. break;
  218. }
  219. if (dwErr != ERROR_NOT_FOUND) { break; }
  220. //
  221. // attempt to allocate a context block for the server
  222. //
  223. pserver = (SERVERCB*)Malloc(sizeof(*pserver));
  224. if (!pserver)
  225. {
  226. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  227. break;
  228. }
  229. //
  230. // initialize the context block allocated
  231. //
  232. ZeroMemory(pserver, sizeof(*pserver));
  233. InitializeListHead(&pserver->lhTransports);
  234. InitializeListHead(&pserver->lhInterfaces);
  235. pserver->lpwsServerName = pszServerNameFmt;
  236. pserver->dwRefCount = 1;
  237. pserver->dwSigniture = SERVERCB_SIG;
  238. //
  239. // Initialize the guid to friendly name mapper
  240. //
  241. dwErr = GuidMapInit(pserver->lpwsServerName, &(pserver->hGuidMap));
  242. if (dwErr != NO_ERROR) { break; }
  243. //
  244. // see if the server-name was specified
  245. //
  246. if (!lpwsServerName || !*lpwsServerName) {
  247. //
  248. // no server-name (or empty server name), connect to local machine
  249. //
  250. pserver->hkeyMachine = HKEY_LOCAL_MACHINE;
  251. dwErr = NO_ERROR;
  252. }
  253. else {
  254. //
  255. // attempt to connect to the remote registry
  256. //
  257. dwErr = RegConnectRegistry(
  258. lpwsServerName, HKEY_LOCAL_MACHINE,
  259. &pserver->hkeyMachine
  260. );
  261. //
  262. // if an error occurred, break
  263. //
  264. if (dwErr != NO_ERROR) { break; }
  265. }
  266. // Add the server to the global table
  267. //
  268. dwErr = ServerCbAdd(pserver);
  269. if (dwErr != NO_ERROR) { break; }
  270. *phMprConfig = (HANDLE)pserver;
  271. dwErr = NO_ERROR;
  272. } while(FALSE);
  273. //
  274. // an error occurred, so return
  275. //
  276. if (dwErr != NO_ERROR)
  277. {
  278. if (pserver != NULL) {
  279. MprConfigServerDisconnect((HANDLE)pserver);
  280. }
  281. }
  282. ReleaseMprConfigLock();
  283. return dwErr;
  284. }
  285. //----------------------------------------------------------------------------
  286. // Function: MprConfigServerDisconnect
  287. //
  288. // Disconnects from the store for the router-service 'hMprConfig'.
  289. // This closes all handles opened to by passing 'hMprConfig'
  290. // to the MprConfig APIs.
  291. //----------------------------------------------------------------------------
  292. VOID APIENTRY
  293. MprConfigServerDisconnect(
  294. IN HANDLE hMprConfig
  295. )
  296. {
  297. SERVERCB* pserver;
  298. LIST_ENTRY *ple, *phead;
  299. pserver = (SERVERCB*)hMprConfig;
  300. if (MprConfigServerValidateCb(pserver) != NO_ERROR) { return; }
  301. // Get the lock
  302. //
  303. AcquireMprConfigLock();
  304. // Decrement the ref count
  305. //
  306. pserver->dwRefCount--;
  307. if (pserver->dwRefCount > 0)
  308. {
  309. ReleaseMprConfigLock();
  310. return;
  311. }
  312. // Remove the SERVERCB from the global table
  313. //
  314. ServerCbDelete( pserver );
  315. ReleaseMprConfigLock();
  316. //
  317. // clean up all the transport objects
  318. //
  319. phead = &pserver->lhTransports;
  320. while (!IsListEmpty(phead)) {
  321. //
  322. // remove the first transport object
  323. //
  324. TRANSPORTCB* ptransport;
  325. ple = RemoveHeadList(phead);
  326. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  327. //
  328. // clean up the object
  329. //
  330. FreeTransport(ptransport);
  331. }
  332. //
  333. // clean up all the interface objects
  334. //
  335. phead = &pserver->lhInterfaces;
  336. while (!IsListEmpty(phead)) {
  337. //
  338. // remove the first interface object
  339. //
  340. INTERFACECB* pinterface;
  341. ple = RemoveHeadList(phead);
  342. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  343. //
  344. // clean up the object
  345. //
  346. FreeInterface(pinterface);
  347. }
  348. //
  349. // clean up the server object's registry keys
  350. //
  351. if (pserver->hkeyParameters) { RegCloseKey(pserver->hkeyParameters); }
  352. if (pserver->hkeyTransports) { RegCloseKey(pserver->hkeyTransports); }
  353. if (pserver->hkeyInterfaces) { RegCloseKey(pserver->hkeyInterfaces); }
  354. //
  355. // if connected to a remote registry, close the connection
  356. //
  357. if (pserver->hkeyMachine && pserver->hkeyMachine != HKEY_LOCAL_MACHINE) {
  358. RegCloseKey(pserver->hkeyMachine);
  359. }
  360. //
  361. // clean up the interface name mapper
  362. //
  363. if (pserver->hGuidMap != NULL) {
  364. GuidMapCleanup (pserver->hGuidMap, TRUE);
  365. }
  366. Free0(pserver->lpwsServerName);
  367. Free(pserver);
  368. return;
  369. }
  370. //----------------------------------------------------------------------------
  371. // Function: MprConfigBufferFree
  372. //
  373. // Frees a buffer allocated by a 'GetInfo' or 'Enum' call.
  374. //----------------------------------------------------------------------------
  375. DWORD APIENTRY
  376. MprConfigBufferFree(
  377. IN LPVOID pBuffer
  378. )
  379. {
  380. Free0(pBuffer);
  381. return NO_ERROR;
  382. }
  383. //----------------------------------------------------------------------------
  384. // Function: MprConfigServerRestore
  385. //
  386. // Restores configuration saved by 'MprConfigServerBackup'.
  387. //----------------------------------------------------------------------------
  388. DWORD APIENTRY
  389. MprConfigServerRestore(
  390. IN HANDLE hMprConfig,
  391. IN LPWSTR lpwsPath
  392. )
  393. {
  394. INT length;
  395. DWORD dwErr;
  396. CHAR szKey[64];
  397. CHAR* pszFile;
  398. CHAR* pszValue;
  399. SERVERCB* pserver;
  400. WCHAR pwsLocalComputerName[128];
  401. DWORD dwLocalComputerSize = sizeof(pwsLocalComputerName) / sizeof(WCHAR);
  402. BOOL bRemote;
  403. pserver = (SERVERCB*)hMprConfig;
  404. dwErr = MprConfigServerValidateCb(pserver);
  405. if (dwErr != NO_ERROR)
  406. {
  407. return dwErr;
  408. }
  409. AcquireMprConfigLock();
  410. dwErr = NO_ERROR;
  411. //
  412. // Record whether we are restoring the config of a remote machine
  413. //
  414. if (!GetComputerName(pwsLocalComputerName, &dwLocalComputerSize)) {
  415. ReleaseMprConfigLock();
  416. return ERROR_CAN_NOT_COMPLETE;
  417. }
  418. bRemote =
  419. (pserver->lpwsServerName != NULL) &&
  420. (*pserver->lpwsServerName != 0) &&
  421. (lstrcmpi(pserver->lpwsServerName, pwsLocalComputerName) != 0);
  422. //
  423. // We require full UNC path for remote load/save
  424. //
  425. if (bRemote) {
  426. ReleaseMprConfigLock();
  427. return ERROR_NOT_SUPPORTED;
  428. #if 0
  429. if ((pserver->lpwsServerName == NULL) ||
  430. (*(pserver->lpwsServerName) == 0) ||
  431. (wcsncmp(lpwsPath, c_szUncPrefix, 2) != 0)) {
  432. ReleaseMprConfigLock();
  433. return ERROR_BAD_PATHNAME;
  434. }
  435. #endif
  436. }
  437. //
  438. // Make sure that the Parameters key, Interfaces key, and
  439. // RouterManagers key are open.
  440. //
  441. if (!pserver->hkeyInterfaces) {
  442. dwErr = AccessRouterSubkey(
  443. pserver->hkeyMachine, c_szInterfaces, TRUE,
  444. &pserver->hkeyInterfaces
  445. );
  446. }
  447. if (!pserver->hkeyTransports) {
  448. dwErr = AccessRouterSubkey(
  449. pserver->hkeyMachine, c_szRouterManagers, TRUE,
  450. &pserver->hkeyTransports
  451. );
  452. }
  453. if (!pserver->hkeyParameters) {
  454. dwErr = AccessRouterSubkey(
  455. pserver->hkeyMachine, c_szParameters, TRUE,
  456. &pserver->hkeyParameters
  457. );
  458. }
  459. //
  460. // Allocate space to hold the full pathname to the .MPR file
  461. //
  462. length = lstrlen(lpwsPath) + lstrlen(c_szMpr) + 1;
  463. pszFile = Malloc(length * sizeof ( WCHAR ) );
  464. if (!pszFile)
  465. {
  466. ReleaseMprConfigLock();
  467. return ERROR_NOT_ENOUGH_MEMORY;
  468. }
  469. //
  470. // Allocate space to hold the values to be read from the .MPR file
  471. //
  472. length = (lstrlen(lpwsPath)+lstrlen(c_szRouterManagers)+1)*sizeof(WCHAR);
  473. pszValue = Malloc( length );
  474. if (!pszValue)
  475. {
  476. ReleaseMprConfigLock();
  477. Free(pszFile);
  478. return ERROR_NOT_ENOUGH_MEMORY;
  479. }
  480. //
  481. // Enable the current process's backup privilege.
  482. //
  483. EnableBackupPrivilege(TRUE, SE_RESTORE_NAME);
  484. dwErr = NO_ERROR;
  485. do {
  486. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  487. wsprintfA(pszFile, "%ls%ls", lpwsPath, c_szMpr);
  488. //
  489. // First check the version. If there is no version data,
  490. // then this is a saved nt4 router config.
  491. //
  492. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  493. wsprintfA(szKey, "%ls", c_szConfigVersion);
  494. GetPrivateProfileStringA(
  495. c_szMprConfigA, szKey, c_szEmptyA, pszValue, length, pszFile
  496. );
  497. if (strcmp(pszValue, c_szEmptyA) == 0) {
  498. dwErr = ERROR_ROUTER_CONFIG_INCOMPATIBLE;
  499. break;
  500. }
  501. //
  502. // Restore the registry keys
  503. //
  504. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  505. wsprintfA(szKey, "%ls", c_szParameters);
  506. GetPrivateProfileStringA(
  507. c_szMprConfigA, szKey, c_szEmptyA, pszValue, length, pszFile
  508. );
  509. dwErr = RegRestoreKeyA(pserver->hkeyParameters, pszValue, REG_FORCE_RESTORE);
  510. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  511. wsprintfA(szKey, "%ls", c_szRouterManagers);
  512. GetPrivateProfileStringA(
  513. c_szMprConfigA, szKey, c_szEmptyA, pszValue, length, pszFile
  514. );
  515. dwErr = RegRestoreKeyA(pserver->hkeyTransports, pszValue, REG_FORCE_RESTORE);
  516. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  517. wsprintfA(szKey, "%ls", c_szInterfaces);
  518. GetPrivateProfileStringA(
  519. c_szMprConfigA, szKey, c_szEmptyA, pszValue, length, pszFile
  520. );
  521. //dwErr = RegRestoreKeyA(pserver->hkeyInterfaces, pszValue, REG_FORCE_RESTORE);
  522. dwErr = RestoreAndTranslateInterfaceKey(pserver, pszValue, REG_FORCE_RESTORE);
  523. //
  524. // Restore the phonebook file
  525. //
  526. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  527. wsprintfA(szKey, "%ls", c_szPhonebook);
  528. GetPrivateProfileStringA(
  529. c_szMprConfigA, szKey, c_szEmptyA, pszValue, length, pszFile
  530. );
  531. {
  532. CHAR* pszTemp;
  533. INT cchSize;
  534. cchSize = lstrlen(c_szUncPrefix) +
  535. lstrlen(c_szRouterPbkPath) + 1;
  536. if (pserver->lpwsServerName) {
  537. cchSize += lstrlen(pserver->lpwsServerName);
  538. }
  539. else {
  540. cchSize += lstrlen(pwsLocalComputerName);
  541. }
  542. pszTemp = Malloc(cchSize * sizeof(WCHAR));
  543. if (!pszTemp) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  544. if (pserver->lpwsServerName) {
  545. if (*(pserver->lpwsServerName) != L'\\') {
  546. wsprintfA(
  547. pszTemp, "\\\\%ls%ls", pserver->lpwsServerName,
  548. c_szRouterPbkPath
  549. );
  550. }
  551. else {
  552. wsprintfA(
  553. pszTemp, "%ls%ls", pserver->lpwsServerName,
  554. c_szRouterPbkPath
  555. );
  556. }
  557. }
  558. else {
  559. wsprintfA(
  560. pszTemp, "\\\\%ls%ls", pwsLocalComputerName,
  561. c_szRouterPbkPath
  562. );
  563. }
  564. CopyFileA(pszValue, pszTemp, FALSE);
  565. Free(pszTemp);
  566. }
  567. } while(FALSE);
  568. //
  569. // Disable backup privileges
  570. //
  571. EnableBackupPrivilege(FALSE, SE_RESTORE_NAME);
  572. ReleaseMprConfigLock();
  573. Free(pszValue);
  574. Free(pszFile);
  575. return dwErr;
  576. }
  577. //----------------------------------------------------------------------------
  578. // Function: MprConfigServerBackup
  579. //
  580. // Backs up a router's configuration.
  581. //----------------------------------------------------------------------------
  582. DWORD APIENTRY
  583. MprConfigServerBackup(
  584. IN HANDLE hMprConfig,
  585. IN LPWSTR lpwsPath
  586. )
  587. {
  588. int length;
  589. DWORD dwErr;
  590. HANDLE hfile;
  591. BOOL bSuccess, bRemote;
  592. WCHAR *pwsBase, *pwsTemp, *pwsComputer;
  593. SERVERCB* pserver;
  594. WCHAR pwsLocalComputerName[128];
  595. DWORD dwLocalComputerSize = sizeof(pwsLocalComputerName) / sizeof(WCHAR);
  596. OSVERSIONINFO Version;
  597. pserver = (SERVERCB*)hMprConfig;
  598. dwErr = MprConfigServerValidateCb(pserver);
  599. if (dwErr != NO_ERROR)
  600. {
  601. return dwErr;
  602. }
  603. AcquireMprConfigLock();
  604. dwErr = NO_ERROR;
  605. //
  606. // Record whether we are saving the config of a remote machine
  607. //
  608. if (!GetComputerName(pwsLocalComputerName, &dwLocalComputerSize)) {
  609. ReleaseMprConfigLock();
  610. return ERROR_CAN_NOT_COMPLETE;
  611. }
  612. bRemote =
  613. (pserver->lpwsServerName != NULL) &&
  614. (*(pserver->lpwsServerName) == 0) &&
  615. (lstrcmpi(pserver->lpwsServerName, pwsLocalComputerName) != 0);
  616. //
  617. // We require full UNC path for remote load/save
  618. //
  619. if (bRemote) {
  620. ReleaseMprConfigLock();
  621. return ERROR_NOT_SUPPORTED;
  622. #if 0
  623. if ((pserver->lpwsServerName == NULL) ||
  624. (*(pserver->lpwsServerName) == 0) ||
  625. (wcsncmp(lpwsPath, c_szUncPrefix, 2) != 0)) {
  626. ReleaseMprConfigLock();
  627. return ERROR_BAD_PATHNAME;
  628. }
  629. #endif
  630. }
  631. //
  632. // Make sure that the Parameters key, Interfaces key, and
  633. // RouterManagers key are open.
  634. //
  635. if (!pserver->hkeyInterfaces) {
  636. dwErr = AccessRouterSubkey(
  637. pserver->hkeyMachine, c_szInterfaces, TRUE,
  638. &pserver->hkeyInterfaces
  639. );
  640. }
  641. if (!pserver->hkeyTransports) {
  642. dwErr = AccessRouterSubkey(
  643. pserver->hkeyMachine, c_szRouterManagers, TRUE,
  644. &pserver->hkeyTransports
  645. );
  646. }
  647. if (!pserver->hkeyParameters) {
  648. dwErr = AccessRouterSubkey(
  649. pserver->hkeyMachine, c_szParameters, TRUE,
  650. &pserver->hkeyParameters
  651. );
  652. }
  653. //
  654. // Allocate enough space to hold any of the strings
  655. // to be constructed below
  656. //
  657. pwsBase = Malloc(
  658. (lstrlen(lpwsPath) + lstrlen(c_szRouterManagers) + 1) *
  659. sizeof(WCHAR)
  660. );
  661. if (!pwsBase) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  662. //
  663. // Enable the current process's backup privileges
  664. //
  665. EnableBackupPrivilege(TRUE, SE_BACKUP_NAME);
  666. do {
  667. //
  668. // Save each key to a filename made from the specified name
  669. // See documentation for RegSaveKey and RegRestoreKey for information
  670. // on which 'lpwsPath' must not contain an extension.
  671. //
  672. // Save the 'Parameters' key
  673. //
  674. lstrcpy(pwsBase, lpwsPath);
  675. lstrcat(pwsBase, c_szParameters);
  676. DeleteFile(pwsBase);
  677. dwErr = RegSaveKey(pserver->hkeyParameters, pwsBase, NULL);
  678. if (dwErr != NO_ERROR) { break; }
  679. //
  680. // Save the 'RouterManagers' key
  681. //
  682. lstrcpy(pwsBase, lpwsPath);
  683. lstrcat(pwsBase, c_szRouterManagers);
  684. DeleteFile(pwsBase);
  685. dwErr = RegSaveKey(pserver->hkeyTransports, pwsBase, NULL);
  686. if (dwErr != NO_ERROR) { break; }
  687. //
  688. // Save the 'Interfaces' key
  689. //
  690. lstrcpy(pwsBase, lpwsPath);
  691. lstrcat(pwsBase, c_szInterfaces);
  692. DeleteFile(pwsBase);
  693. dwErr = TranslateAndSaveInterfaceKey (pserver, pwsBase, NULL);
  694. if (dwErr != NO_ERROR) { break; }
  695. //
  696. // Copy the phonebook file;
  697. // first we construct the path to the remote machine's phonebook file.
  698. //
  699. lstrcpy(pwsBase, lpwsPath);
  700. lstrcat(pwsBase, c_szPhonebook);
  701. //
  702. // Construct the computer name
  703. //
  704. if (pserver->lpwsServerName && *(pserver->lpwsServerName)) {
  705. pwsComputer =
  706. Malloc(
  707. (lstrlen(pserver->lpwsServerName) + 3) * sizeof(WCHAR)
  708. );
  709. lstrcpy(pwsComputer, c_szUncPrefix);
  710. lstrcat(pwsComputer, pserver->lpwsServerName);
  711. }
  712. else {
  713. pwsComputer =
  714. Malloc(
  715. (lstrlen(pwsLocalComputerName) + 3) * sizeof(WCHAR)
  716. );
  717. lstrcpy(pwsComputer, c_szUncPrefix);
  718. lstrcat(pwsComputer, pwsLocalComputerName);
  719. }
  720. pwsTemp = Malloc(
  721. (lstrlen(pwsComputer) + lstrlen(c_szRouterPbkPath) + 1) *
  722. sizeof(WCHAR)
  723. );
  724. if (!pwsTemp) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  725. lstrcpy(pwsTemp, pwsComputer);
  726. lstrcat(pwsTemp, c_szRouterPbkPath);
  727. if (!(bSuccess = CopyFile(pwsTemp, pwsBase, FALSE))) {
  728. dwErr = GetLastError();
  729. if (dwErr == ERROR_FILE_NOT_FOUND) {
  730. hfile = CreateFile(
  731. pwsBase, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  732. FILE_ATTRIBUTE_NORMAL, NULL
  733. );
  734. if (hfile == INVALID_HANDLE_VALUE) {
  735. dwErr = GetLastError(); break;
  736. }
  737. CloseHandle(hfile);
  738. dwErr = NO_ERROR; bSuccess = TRUE;
  739. }
  740. }
  741. Free0(pwsComputer);
  742. Free(pwsTemp);
  743. if (!bSuccess) { break; }
  744. //
  745. // Create a file with the specified name and fill in information.
  746. //
  747. lstrcpy(pwsBase, lpwsPath);
  748. lstrcat(pwsBase, c_szMpr);
  749. hfile = CreateFile(
  750. pwsBase, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  751. FILE_ATTRIBUTE_NORMAL, NULL
  752. );
  753. if (hfile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); break; }
  754. CloseHandle(hfile);
  755. //
  756. // Now write the '[MprConfig]' section of the file
  757. // The section looks like this:
  758. //
  759. // [MprConfig]
  760. // Parameters=<file>Parameters
  761. // RouterManagers=<file>RouterManagers
  762. // Interfaces=<file>Interfaces
  763. // Phonebook=<file>Phonebook
  764. // ConfigVersion=<build> // NT 5 and on only
  765. //
  766. // What we pass to WritePrivateProfileSectionA is a NULL-separated
  767. // list of 4 strings.
  768. //
  769. // Note that the following uses ANSI strings, not Unicode.
  770. //
  771. {
  772. CHAR* psz;
  773. CHAR* pszTemp;
  774. CHAR* pszFile;
  775. //
  776. // Make an ANSI copy of the filename.
  777. // allocate len*sizeof ( WCHAR ) to be safe
  778. // otherwise this will break DBCS
  779. //
  780. pszFile = Malloc((lstrlen(pwsBase) + 1) * sizeof (WCHAR));
  781. if (!pszFile) { break; }
  782. #pragma prefast(suppress:69, "Inefficient use of wsprintf: dont need")
  783. wsprintfA(pszFile, "%ls", pwsBase);
  784. //
  785. // Allocate the list to be passed to WritePrivateProfileSection
  786. //
  787. length = 1;
  788. length += lstrlen(lpwsPath) + 2 * lstrlen(c_szParameters) + 2;
  789. length += lstrlen(lpwsPath) + 2 * lstrlen(c_szRouterManagers) + 2;
  790. length += lstrlen(lpwsPath) + 2 * lstrlen(c_szInterfaces) + 2;
  791. length += lstrlen(lpwsPath) + 2 * lstrlen(c_szPhonebook) + 2;
  792. length += 5 + 2 * lstrlen(c_szConfigVersion) + 2;
  793. length = length * sizeof (WCHAR);
  794. pszTemp = Malloc(length);
  795. if (!pszTemp) {
  796. Free(pszFile); dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  797. }
  798. //
  799. // Fill the list with strings, one for each line in the final file
  800. //
  801. ZeroMemory(pszTemp, length);
  802. ZeroMemory(&Version, sizeof(Version));
  803. Version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  804. GetVersionEx(&Version);
  805. psz = pszTemp;
  806. wsprintfA(
  807. psz, "%ls=%ls%ls", c_szParameters, lpwsPath, c_szParameters
  808. );
  809. psz += lstrlenA(psz) + 1;
  810. wsprintfA(
  811. psz, "%ls=%ls%ls", c_szRouterManagers, lpwsPath,
  812. c_szRouterManagers
  813. );
  814. psz += lstrlenA(psz) + 1;
  815. wsprintfA(
  816. psz, "%ls=%ls%ls", c_szInterfaces, lpwsPath, c_szInterfaces
  817. );
  818. psz += lstrlenA(psz) + 1;
  819. wsprintfA(
  820. psz, "%ls=%ls%ls", c_szPhonebook, lpwsPath, c_szPhonebook
  821. );
  822. psz += lstrlenA(psz) + 1;
  823. wsprintfA(
  824. psz, "%ls=%d", c_szConfigVersion, Version.dwBuildNumber
  825. );
  826. //
  827. // Commit the list of strings to the file
  828. //
  829. if (!WritePrivateProfileSectionA(
  830. c_szMprConfigA, pszTemp, pszFile
  831. )) {
  832. dwErr = GetLastError();
  833. }
  834. Free(pszTemp);
  835. Free(pszFile);
  836. }
  837. } while(FALSE);
  838. //
  839. // Disable backup privileges
  840. //
  841. EnableBackupPrivilege(FALSE, SE_BACKUP_NAME);
  842. ReleaseMprConfigLock();
  843. Free0(pwsBase);
  844. return dwErr;
  845. }
  846. //----------------------------------------------------------------------------
  847. // Function: MprConfigServerRefresh
  848. //
  849. // Reloads all loaded lists, and flushes all cached objects which are marked
  850. // for deletion.
  851. //----------------------------------------------------------------------------
  852. DWORD APIENTRY
  853. MprConfigServerRefresh(
  854. IN HANDLE hMprConfig
  855. )
  856. {
  857. DWORD dwErr;
  858. SERVERCB* pserver;
  859. TRANSPORTCB* ptransport;
  860. INTERFACECB* pinterface;
  861. IFTRANSPORTCB* piftransport;
  862. LIST_ENTRY *ple, *phead, *ple2, *phead2;
  863. pserver = (SERVERCB*)hMprConfig;
  864. dwErr = MprConfigServerValidateCb(pserver);
  865. if (dwErr != NO_ERROR)
  866. {
  867. return dwErr;
  868. }
  869. AcquireMprConfigLock();
  870. //
  871. // If the router-level parameters are loaded, refresh them
  872. //
  873. if (pserver->bParametersLoaded) {
  874. dwErr = LoadParameters(pserver);
  875. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  876. }
  877. //
  878. // If the transports-list is loaded, refresh it.
  879. //
  880. if (pserver->bTransportsLoaded) {
  881. dwErr = LoadTransports(pserver);
  882. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  883. }
  884. //
  885. // If the interfaces-list is loaded, refresh it.
  886. //
  887. if (pserver->bInterfacesLoaded) {
  888. dwErr = LoadInterfaces(pserver);
  889. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  890. //
  891. // Reload the interface-transports list for each interface
  892. // which has its interface-transports list loaded.
  893. //
  894. phead = &pserver->lhInterfaces;
  895. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  896. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  897. if (pinterface->bIfTransportsLoaded) {
  898. dwErr = LoadIfTransports(pinterface);
  899. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  900. }
  901. }
  902. }
  903. //
  904. // Clean up all the transport objects marked for deletion
  905. //
  906. phead = &pserver->lhTransports;
  907. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  908. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  909. if (!ptransport->bDeleted) { continue; }
  910. //
  911. // Clean up the object, adjusting our list-pointer back by one.
  912. //
  913. ple = ple->Blink; RemoveEntryList(&ptransport->leNode);
  914. FreeTransport(ptransport);
  915. }
  916. //
  917. // Clean up all the interface objects marked for deletion
  918. //
  919. phead = &pserver->lhInterfaces;
  920. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  921. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  922. if (pinterface->bDeleted) {
  923. //
  924. // Clean up the object, adjusting our list-pointer back by one.
  925. //
  926. ple = ple->Blink; RemoveEntryList(&pinterface->leNode);
  927. FreeInterface(pinterface);
  928. continue;
  929. }
  930. //
  931. // Clean up all the interface-transport objects marked for deletion
  932. //
  933. phead2 = &pinterface->lhIfTransports;
  934. for (ple2 = phead2->Flink; ple2 != phead2; ple2 = ple2->Flink) {
  935. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  936. if (!piftransport->bDeleted) { continue; }
  937. //
  938. // Clean up the object, adjusting the list-pointer back by one.
  939. //
  940. ple2 = ple2->Blink; RemoveEntryList(&piftransport->leNode);
  941. FreeIfTransport(piftransport);
  942. }
  943. }
  944. GuidMapCleanup (pserver->hGuidMap, TRUE);
  945. pserver->hGuidMap = NULL;
  946. // Now that we've cleaned it up, we have to reinitialize it
  947. // since the map gets overwritten (to all 0's) let's just
  948. // reinit the whole damned thing.
  949. GuidMapInit(pserver->lpwsServerName, &(pserver->hGuidMap));
  950. ReleaseMprConfigLock();
  951. return NO_ERROR;
  952. }
  953. //----------------------------------------------------------------------------
  954. // Function: MprConfigServerGetInfo
  955. //
  956. // Retrieves router-level information from the registry.
  957. //----------------------------------------------------------------------------
  958. DWORD APIENTRY
  959. MprConfigServerGetInfo(
  960. IN HANDLE hMprConfig,
  961. IN DWORD dwLevel,
  962. OUT LPBYTE* lplpBuffer
  963. )
  964. {
  965. DWORD dwErr;
  966. SERVERCB *pserver;
  967. MPR_SERVER_0* pItem;
  968. if (!hMprConfig ||
  969. (dwLevel != 0) ||
  970. !lplpBuffer) { return ERROR_INVALID_PARAMETER; }
  971. pserver = (SERVERCB*)hMprConfig;
  972. dwErr = MprConfigServerValidateCb(pserver);
  973. if (dwErr != NO_ERROR)
  974. {
  975. return dwErr;
  976. }
  977. AcquireMprConfigLock();
  978. //
  979. // If the parameters aren't loaded, load them now
  980. //
  981. if (!pserver->bParametersLoaded ||
  982. TimeStampChanged(
  983. pserver->hkeyParameters, &pserver->ftParametersStamp)) {
  984. dwErr = LoadParameters(pserver);
  985. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  986. pserver->bParametersLoaded = TRUE;
  987. }
  988. *lplpBuffer = NULL;
  989. //
  990. // Allocate memory for the information
  991. //
  992. pItem = (MPR_SERVER_0*)Malloc(sizeof(*pItem));
  993. if (!pItem) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  994. ZeroMemory(pItem, sizeof(*pItem));
  995. //
  996. // Copy the server-info from the context block
  997. //
  998. pItem->fLanOnlyMode =
  999. (pserver->fRouterType == 0x00000002) ? TRUE : FALSE;
  1000. *lplpBuffer = (LPBYTE)pItem;
  1001. ReleaseMprConfigLock();
  1002. return NO_ERROR;
  1003. }
  1004. //----------------------------------------------------------------------------
  1005. // Function: MprConfigTransportCreate
  1006. //
  1007. // Adds a router-transport to the store for the router-service.
  1008. //----------------------------------------------------------------------------
  1009. DWORD APIENTRY
  1010. MprConfigTransportCreate(
  1011. IN HANDLE hMprConfig,
  1012. IN DWORD dwTransportId,
  1013. IN LPWSTR lpwsTransportName OPTIONAL,
  1014. IN LPBYTE pGlobalInfo,
  1015. IN DWORD dwGlobalInfoSize,
  1016. IN LPBYTE pClientInterfaceInfo OPTIONAL,
  1017. IN DWORD dwClientInterfaceInfoSize OPTIONAL,
  1018. IN LPWSTR lpwsDLLPath OPTIONAL,
  1019. OUT HANDLE* phRouterTransport
  1020. )
  1021. {
  1022. DWORD dwErr;
  1023. SERVERCB *pserver;
  1024. TRANSPORTCB* ptransport;
  1025. LIST_ENTRY *ple, *phead;
  1026. if (!phRouterTransport) {return ERROR_INVALID_PARAMETER;}
  1027. *phRouterTransport = NULL;
  1028. pserver = (SERVERCB*)hMprConfig;
  1029. dwErr = MprConfigServerValidateCb(pserver);
  1030. if (dwErr != NO_ERROR)
  1031. {
  1032. return dwErr;
  1033. }
  1034. AcquireMprConfigLock();
  1035. //
  1036. // If the list of transports is not loaded, load it
  1037. //
  1038. if (!pserver->bTransportsLoaded ||
  1039. TimeStampChanged(
  1040. pserver->hkeyTransports, &pserver->ftTransportsStamp)) {
  1041. dwErr = LoadTransports(pserver);
  1042. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  1043. pserver->bTransportsLoaded = TRUE;
  1044. }
  1045. //
  1046. // Search the list of transports for the one to be created
  1047. //
  1048. ptransport = NULL;
  1049. phead = &pserver->lhTransports;
  1050. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  1051. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1052. if (ptransport->bDeleted) { continue; }
  1053. if (ptransport->dwTransportId >= dwTransportId) { break; }
  1054. }
  1055. //
  1056. // If the transport already exists, do a SetInfo instead
  1057. //
  1058. if (ptransport && ptransport->dwTransportId == dwTransportId) {
  1059. *phRouterTransport = (HANDLE)ptransport;
  1060. dwErr = MprConfigTransportSetInfo(
  1061. hMprConfig,
  1062. *phRouterTransport,
  1063. pGlobalInfo,
  1064. dwGlobalInfoSize,
  1065. pClientInterfaceInfo,
  1066. dwClientInterfaceInfoSize,
  1067. lpwsDLLPath
  1068. );
  1069. ReleaseMprConfigLock();
  1070. return dwErr;
  1071. }
  1072. //
  1073. // Allocate a new context block
  1074. //
  1075. ptransport = (TRANSPORTCB*)Malloc(sizeof(*ptransport));
  1076. if (!ptransport) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  1077. do {
  1078. DWORD dwDisposition;
  1079. const WCHAR *lpwsKey;
  1080. WCHAR wszTransport[10];
  1081. //
  1082. // Initialize the transport context
  1083. //
  1084. ZeroMemory(ptransport, sizeof(*ptransport));
  1085. ptransport->dwTransportId = dwTransportId;
  1086. //
  1087. // If the server doesn't have the RouterManagers key open, create it
  1088. //
  1089. if (!pserver->hkeyTransports) {
  1090. dwErr = AccessRouterSubkey(
  1091. pserver->hkeyMachine, c_szRouterManagers, TRUE,
  1092. &pserver->hkeyTransports
  1093. );
  1094. if (dwErr != NO_ERROR) { break; }
  1095. }
  1096. //
  1097. // If the transport name is specified, use it as the key name;
  1098. // otherwise, if the transport ID is recognized, use its string;
  1099. // otherwise, convert the transport ID to a string and use that
  1100. //
  1101. if (lpwsTransportName && lstrlen(lpwsTransportName)) {
  1102. lpwsKey = lpwsTransportName;
  1103. }
  1104. else
  1105. if (dwTransportId == PID_IP) {
  1106. lpwsKey = c_szIP;
  1107. }
  1108. else
  1109. if (dwTransportId == PID_IPX) {
  1110. lpwsKey = c_szIPX;
  1111. }
  1112. else {
  1113. wsprintf(wszTransport, L"%d", dwTransportId);
  1114. lpwsKey = wszTransport;
  1115. }
  1116. ptransport->lpwsTransportKey = StrDupW(lpwsKey);
  1117. if (!ptransport->lpwsTransportKey) {
  1118. dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  1119. }
  1120. //
  1121. // Create a key for the transport in the registry
  1122. //
  1123. dwErr = RegCreateKeyEx(
  1124. pserver->hkeyTransports, lpwsKey, 0, NULL, 0,
  1125. KEY_READ | KEY_WRITE | DELETE, NULL, &ptransport->hkey, &dwDisposition
  1126. );
  1127. if (dwErr != NO_ERROR) { break; }
  1128. //
  1129. // Update the time-stamp for the 'RouterManagers' key
  1130. // now that we have created a new subkey underneath it.
  1131. //
  1132. dwErr = UpdateTimeStamp(
  1133. pserver->hkeyTransports, &pserver->ftTransportsStamp
  1134. );
  1135. //
  1136. // So far, so good; put the context in the list of transports;
  1137. // (the search done above told us the insertion point)
  1138. //
  1139. InsertTailList(ple, &ptransport->leNode);
  1140. do {
  1141. //
  1142. // Set the transport ID
  1143. //
  1144. dwErr = RegSetValueEx(
  1145. ptransport->hkey, c_szProtocolId, 0, REG_DWORD,
  1146. (BYTE*)&dwTransportId, sizeof(dwTransportId)
  1147. );
  1148. if (dwErr != NO_ERROR) { break; }
  1149. //
  1150. // Now call SetInfo to save the information
  1151. //
  1152. dwErr = MprConfigTransportSetInfo(
  1153. hMprConfig,
  1154. (HANDLE)ptransport,
  1155. pGlobalInfo,
  1156. dwGlobalInfoSize,
  1157. pClientInterfaceInfo,
  1158. dwClientInterfaceInfoSize,
  1159. lpwsDLLPath
  1160. );
  1161. } while (FALSE);
  1162. //
  1163. // If that failed, remove everything and bail out
  1164. //
  1165. if (dwErr != NO_ERROR) {
  1166. MprConfigTransportDelete(hMprConfig, (HANDLE)ptransport);
  1167. ReleaseMprConfigLock();
  1168. return dwErr;
  1169. }
  1170. //
  1171. // Return successfully
  1172. //
  1173. *phRouterTransport = (HANDLE)ptransport;
  1174. ReleaseMprConfigLock();
  1175. return NO_ERROR;
  1176. } while (FALSE);
  1177. //
  1178. // Something went wrong, so return
  1179. //
  1180. ReleaseMprConfigLock();
  1181. FreeTransport(ptransport);
  1182. return dwErr;
  1183. }
  1184. //----------------------------------------------------------------------------
  1185. // Function: MprConfigTransportDelete
  1186. //
  1187. // Removes a router-transport to the store for the router-service
  1188. // After this call, 'hRouterTransport' is no longer a valid handle.
  1189. //----------------------------------------------------------------------------
  1190. DWORD APIENTRY
  1191. MprConfigTransportDelete(
  1192. IN HANDLE hMprConfig,
  1193. IN HANDLE hRouterTransport
  1194. )
  1195. {
  1196. DWORD dwErr;
  1197. SERVERCB* pserver;
  1198. TRANSPORTCB* ptransport;
  1199. if (!hRouterTransport) { return ERROR_INVALID_PARAMETER; }
  1200. pserver = (SERVERCB*)hMprConfig;
  1201. dwErr = MprConfigServerValidateCb(pserver);
  1202. if (dwErr != NO_ERROR)
  1203. {
  1204. return dwErr;
  1205. }
  1206. AcquireMprConfigLock();
  1207. ptransport = (TRANSPORTCB*)hRouterTransport;
  1208. //
  1209. // remove the transport from the list of transports
  1210. //
  1211. RemoveEntryList(&ptransport->leNode);
  1212. //
  1213. // if the server doesn't have the RouterManagers key open, open it
  1214. //
  1215. dwErr = NO_ERROR;
  1216. if (!pserver->hkeyTransports) {
  1217. dwErr = AccessRouterSubkey(
  1218. pserver->hkeyMachine, c_szRouterManagers, FALSE,
  1219. &pserver->hkeyTransports
  1220. );
  1221. }
  1222. //
  1223. // remove the transport's key from the registry
  1224. //
  1225. if (dwErr == NO_ERROR) {
  1226. dwErr = RegDeleteTree(
  1227. pserver->hkeyTransports, ptransport->lpwsTransportKey
  1228. );
  1229. //
  1230. // Update the time-stamp for the 'RouterManagers' key
  1231. // now that we have deleted a subtree underneath it.
  1232. //
  1233. UpdateTimeStamp(pserver->hkeyTransports, &pserver->ftTransportsStamp);
  1234. }
  1235. //
  1236. // clean up the transport object
  1237. //
  1238. FreeTransport(ptransport);
  1239. ReleaseMprConfigLock();
  1240. return dwErr;
  1241. }
  1242. //----------------------------------------------------------------------------
  1243. // Function: MprConfigTransportGetHandle
  1244. //
  1245. // Retrieves a handle to a transport's configuration.
  1246. //----------------------------------------------------------------------------
  1247. DWORD APIENTRY
  1248. MprConfigTransportGetHandle(
  1249. IN HANDLE hMprConfig,
  1250. IN DWORD dwTransportId,
  1251. OUT HANDLE* phRouterTransport
  1252. )
  1253. {
  1254. DWORD i, dwErr;
  1255. SERVERCB *pserver;
  1256. TRANSPORTCB* ptransport;
  1257. LIST_ENTRY *ple, *phead;
  1258. if (!phRouterTransport) {return ERROR_INVALID_PARAMETER;}
  1259. pserver = (SERVERCB*)hMprConfig;
  1260. dwErr = MprConfigServerValidateCb(pserver);
  1261. if (dwErr != NO_ERROR)
  1262. {
  1263. return dwErr;
  1264. }
  1265. *phRouterTransport = NULL;
  1266. AcquireMprConfigLock();
  1267. //
  1268. // If the list of transports is not loaded, load it
  1269. //
  1270. if (!pserver->bTransportsLoaded ||
  1271. TimeStampChanged(
  1272. pserver->hkeyTransports, &pserver->ftTransportsStamp)) {
  1273. dwErr = LoadTransports(pserver);
  1274. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  1275. pserver->bTransportsLoaded = TRUE;
  1276. }
  1277. //
  1278. // Search the list of transports for the one requested
  1279. //
  1280. ptransport = NULL;
  1281. phead = &pserver->lhTransports;
  1282. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  1283. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1284. if (ptransport->bDeleted) { continue; }
  1285. if (ptransport->dwTransportId >= dwTransportId) { break; }
  1286. }
  1287. //
  1288. // If the transport requested was found, return successfully
  1289. //
  1290. if (ptransport && ptransport->dwTransportId == dwTransportId) {
  1291. *phRouterTransport = (HANDLE)ptransport;
  1292. ReleaseMprConfigLock();
  1293. return NO_ERROR;
  1294. }
  1295. ReleaseMprConfigLock();
  1296. return ERROR_UNKNOWN_PROTOCOL_ID;
  1297. }
  1298. //----------------------------------------------------------------------------
  1299. // Function: MprConfigTransportSetInfo
  1300. //
  1301. // Changes the cofiguration of a router-transport in the store.
  1302. //----------------------------------------------------------------------------
  1303. DWORD APIENTRY
  1304. MprConfigTransportSetInfo(
  1305. IN HANDLE hMprConfig,
  1306. IN HANDLE hRouterTransport,
  1307. IN LPBYTE pGlobalInfo,
  1308. IN DWORD dwGlobalInfoSize,
  1309. IN LPBYTE pClientInterfaceInfo,
  1310. IN DWORD dwClientInterfaceInfoSize,
  1311. IN LPWSTR lpwsDLLPath
  1312. )
  1313. {
  1314. DWORD dwErr;
  1315. SERVERCB* pserver;
  1316. TRANSPORTCB* ptransport;
  1317. //
  1318. // Validate parameters
  1319. //
  1320. if (!hRouterTransport) { return ERROR_INVALID_PARAMETER; }
  1321. if (!pGlobalInfo &&
  1322. !pClientInterfaceInfo &&
  1323. !lpwsDLLPath) { return NO_ERROR; }
  1324. pserver = (SERVERCB*)hMprConfig;
  1325. dwErr = MprConfigServerValidateCb(pserver);
  1326. if (dwErr != NO_ERROR)
  1327. {
  1328. return dwErr;
  1329. }
  1330. AcquireMprConfigLock();
  1331. ptransport = (TRANSPORTCB*)hRouterTransport;
  1332. if (ptransport->bDeleted) { ReleaseMprConfigLock(); return ERROR_UNKNOWN_PROTOCOL_ID; }
  1333. do {
  1334. //
  1335. // Set the GlobalInfo
  1336. //
  1337. if (pGlobalInfo) {
  1338. dwErr = RegSetValueEx(
  1339. ptransport->hkey, c_szGlobalInfo, 0, REG_BINARY,
  1340. pGlobalInfo, dwGlobalInfoSize
  1341. );
  1342. if (dwErr != NO_ERROR) { break; }
  1343. }
  1344. //
  1345. // Set the ClientInterfaceInfo
  1346. //
  1347. if (pClientInterfaceInfo) {
  1348. dwErr = RegSetValueEx(
  1349. ptransport->hkey, c_szGlobalInterfaceInfo, 0,
  1350. REG_BINARY, pClientInterfaceInfo,
  1351. dwClientInterfaceInfoSize
  1352. );
  1353. if (dwErr != NO_ERROR) { break; }
  1354. }
  1355. //
  1356. // Set the DLL path
  1357. //
  1358. if (lpwsDLLPath) {
  1359. DWORD dwSize = (lstrlen(lpwsDLLPath) + 1) * sizeof(WCHAR);
  1360. dwErr = RegSetValueEx(
  1361. ptransport->hkey, c_szDLLPath, 0, REG_EXPAND_SZ,
  1362. (BYTE*)lpwsDLLPath, dwSize
  1363. );
  1364. if (dwErr != NO_ERROR) { break; }
  1365. }
  1366. dwErr = NO_ERROR;
  1367. } while(FALSE);
  1368. ReleaseMprConfigLock();
  1369. return dwErr;
  1370. }
  1371. //----------------------------------------------------------------------------
  1372. // Function: MprConfigTransportGetInfo
  1373. //
  1374. // Reads the cofiguration of a router-transport from the store.
  1375. //----------------------------------------------------------------------------
  1376. DWORD APIENTRY
  1377. MprConfigTransportGetInfo(
  1378. IN HANDLE hMprConfig,
  1379. IN HANDLE hRouterTransport,
  1380. IN OUT LPBYTE* ppGlobalInfo OPTIONAL,
  1381. OUT LPDWORD lpdwGlobalInfoSize OPTIONAL,
  1382. IN OUT LPBYTE* ppClientInterfaceInfo OPTIONAL,
  1383. OUT LPDWORD lpdwClientInterfaceInfoSize OPTIONAL,
  1384. IN OUT LPWSTR* lplpwsDLLPath OPTIONAL
  1385. )
  1386. {
  1387. DWORD dwErr;
  1388. SERVERCB* pserver;
  1389. TRANSPORTCB* ptransport;
  1390. //
  1391. // Validate parameters
  1392. //
  1393. if (!hRouterTransport) { return ERROR_INVALID_PARAMETER; }
  1394. if (!ppGlobalInfo &&
  1395. !ppClientInterfaceInfo &&
  1396. !lplpwsDLLPath) { return NO_ERROR; }
  1397. if ((ppGlobalInfo && !lpdwGlobalInfoSize) ||
  1398. (ppClientInterfaceInfo && !lpdwClientInterfaceInfoSize)) {
  1399. return ERROR_INVALID_PARAMETER;
  1400. }
  1401. pserver = (SERVERCB*)hMprConfig;
  1402. dwErr = MprConfigServerValidateCb(pserver);
  1403. if (dwErr != NO_ERROR)
  1404. {
  1405. return dwErr;
  1406. }
  1407. AcquireMprConfigLock();
  1408. //
  1409. // Initialize all parameters
  1410. //
  1411. if (ppGlobalInfo) { *ppGlobalInfo = NULL; }
  1412. if (ppClientInterfaceInfo) { *ppClientInterfaceInfo = NULL; }
  1413. if (lpdwGlobalInfoSize) { *lpdwGlobalInfoSize = 0; }
  1414. if (lpdwClientInterfaceInfoSize) { *lpdwClientInterfaceInfoSize = 0; }
  1415. if (lplpwsDLLPath) { *lplpwsDLLPath = NULL; }
  1416. ptransport = (TRANSPORTCB*)hRouterTransport;
  1417. if (ptransport->bDeleted) { ReleaseMprConfigLock(); return ERROR_UNKNOWN_PROTOCOL_ID; }
  1418. do {
  1419. DWORD dwType, dwSize;
  1420. //
  1421. // Retrieve the global info
  1422. //
  1423. if (ppGlobalInfo) {
  1424. dwErr = QueryValue(
  1425. ptransport->hkey, c_szGlobalInfo, ppGlobalInfo,
  1426. lpdwGlobalInfoSize
  1427. );
  1428. if (dwErr != NO_ERROR) { break; }
  1429. }
  1430. //
  1431. // Retrieve the client-interface info
  1432. //
  1433. if (ppClientInterfaceInfo) {
  1434. dwErr = QueryValue(
  1435. ptransport->hkey, c_szGlobalInterfaceInfo,
  1436. ppClientInterfaceInfo, lpdwClientInterfaceInfoSize
  1437. );
  1438. if (dwErr != NO_ERROR) { break; }
  1439. }
  1440. //
  1441. // Retrieve the DLL path
  1442. //
  1443. if (lplpwsDLLPath) {
  1444. dwErr = QueryValue(
  1445. ptransport->hkey, c_szDLLPath, (LPBYTE*)lplpwsDLLPath,
  1446. &dwSize
  1447. );
  1448. if (dwErr != NO_ERROR) { break; }
  1449. }
  1450. //
  1451. // All went well, return successfully
  1452. //
  1453. ReleaseMprConfigLock();
  1454. return NO_ERROR;
  1455. } while(FALSE);
  1456. //
  1457. // An error occurred, free all parameters and return failure
  1458. //
  1459. if (ppGlobalInfo) {
  1460. Free0(*ppGlobalInfo); *ppGlobalInfo = NULL; *lpdwGlobalInfoSize = 0;
  1461. }
  1462. if (ppClientInterfaceInfo) {
  1463. Free0(*ppClientInterfaceInfo);
  1464. *ppClientInterfaceInfo = NULL; *lpdwClientInterfaceInfoSize = 0;
  1465. }
  1466. if (lplpwsDLLPath) {
  1467. Free0(*lplpwsDLLPath); *lplpwsDLLPath = NULL;
  1468. }
  1469. ReleaseMprConfigLock();
  1470. return dwErr;
  1471. }
  1472. //----------------------------------------------------------------------------
  1473. // Function: MprConfigTransportEnum
  1474. //
  1475. // Enumerates the configured router-transport in the router-service store.
  1476. //----------------------------------------------------------------------------
  1477. DWORD APIENTRY
  1478. MprConfigTransportEnum(
  1479. IN HANDLE hMprConfig,
  1480. IN DWORD dwLevel,
  1481. IN OUT LPBYTE* lplpBuffer, // MPR_TRANSPORT_0
  1482. IN DWORD dwPrefMaxLen,
  1483. OUT LPDWORD lpdwEntriesRead,
  1484. OUT LPDWORD lpdwTotalEntries,
  1485. IN OUT LPDWORD lpdwResumeHandle OPTIONAL
  1486. )
  1487. {
  1488. SERVERCB* pserver;
  1489. TRANSPORTCB* ptransport;
  1490. LIST_ENTRY *ple, *phead, *pleStart;
  1491. MPR_TRANSPORT_0 *pItem, *pItemTable;
  1492. DWORD dwErr, i, dwStartIndex, dwItemCount, dwItemTotal;
  1493. if (hMprConfig==NULL)
  1494. return ERROR_INVALID_PARAMETER;
  1495. if ((dwLevel != 0) ||
  1496. !lplpBuffer ||
  1497. dwPrefMaxLen < sizeof(*pItem) ||
  1498. !lpdwEntriesRead ||
  1499. !lpdwTotalEntries) { return ERROR_INVALID_PARAMETER; }
  1500. pserver = (SERVERCB*)hMprConfig;
  1501. dwErr = MprConfigServerValidateCb(pserver);
  1502. if (dwErr != NO_ERROR)
  1503. {
  1504. return dwErr;
  1505. }
  1506. AcquireMprConfigLock();
  1507. *lplpBuffer = NULL;
  1508. *lpdwEntriesRead = 0;
  1509. *lpdwTotalEntries = 0;
  1510. //
  1511. // See whether the enumeration is being continued or being begun.
  1512. //
  1513. if (lpdwResumeHandle && *lpdwResumeHandle) {
  1514. //
  1515. // A resumption handle is specified,
  1516. // so we assume that our list of transports is up-to-date,
  1517. // and we just count off the requested number of transports
  1518. // from our list starting from the specified index.
  1519. //
  1520. dwStartIndex = *lpdwResumeHandle;
  1521. }
  1522. else {
  1523. //
  1524. // No resumption handle was specified, so we may need to read
  1525. // all the router-managers in order to get 'lpdwTotalEntries'
  1526. //
  1527. dwStartIndex = 0;
  1528. if (!pserver->bTransportsLoaded ||
  1529. TimeStampChanged(
  1530. pserver->hkeyTransports, &pserver->ftTransportsStamp)) {
  1531. dwErr = LoadTransports(pserver);
  1532. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  1533. pserver->bTransportsLoaded = TRUE;
  1534. }
  1535. }
  1536. //
  1537. // Find the position in the list to start from
  1538. //
  1539. phead = &pserver->lhTransports;
  1540. for (i = 0, ple = phead->Flink;
  1541. i < dwStartIndex && ple != phead; ple = ple->Flink) {
  1542. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1543. if (!ptransport->bDeleted) { ++i; }
  1544. }
  1545. //
  1546. // if there aren't enough items to complete the request, fail
  1547. //
  1548. if (ple == phead) { ReleaseMprConfigLock(); return ERROR_NO_MORE_ITEMS; }
  1549. pleStart = ple;
  1550. //
  1551. // count off the number of items requested
  1552. //
  1553. dwItemCount = dwPrefMaxLen / sizeof(*pItemTable);
  1554. for (i = 0; i < dwItemCount && ple != phead; ple = ple->Flink) {
  1555. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1556. if (!ptransport->bDeleted) { ++i; }
  1557. }
  1558. dwItemCount = i;
  1559. //
  1560. // finish counting off, to get the total number of items
  1561. //
  1562. for ( ; ple != phead; ple = ple->Flink) {
  1563. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1564. if (!ptransport->bDeleted) { ++i; }
  1565. }
  1566. dwItemTotal = i;
  1567. //
  1568. // we now have the number of items to be retrieved, so allocate space
  1569. //
  1570. pItemTable = (MPR_TRANSPORT_0*)Malloc(dwItemCount * sizeof(*pItem));
  1571. if (!pItemTable) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  1572. ZeroMemory(pItemTable, dwItemCount * sizeof(*pItem));
  1573. //
  1574. // now fill in the items using the listed transport objects
  1575. //
  1576. for (i = 0, ple = pleStart; i < dwItemCount; ple = ple->Flink) {
  1577. //
  1578. // get the next transport-object in our list
  1579. //
  1580. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  1581. if (ptransport->bDeleted) { continue; }
  1582. //
  1583. // fill in information for the corresponding array item
  1584. //
  1585. pItem = pItemTable + i++;
  1586. pItem->dwTransportId = ptransport->dwTransportId;
  1587. pItem->hTransport = (HANDLE)ptransport;
  1588. if (ptransport->lpwsTransportKey) {
  1589. lstrcpyn(
  1590. pItem->wszTransportName, ptransport->lpwsTransportKey,
  1591. MAX_TRANSPORT_NAME_LEN + 1
  1592. );
  1593. }
  1594. }
  1595. *lplpBuffer = (LPBYTE)pItemTable;
  1596. *lpdwEntriesRead = dwItemCount;
  1597. *lpdwTotalEntries = dwItemTotal;
  1598. if (lpdwResumeHandle) { *lpdwResumeHandle = dwStartIndex + dwItemCount; }
  1599. ReleaseMprConfigLock();
  1600. return NO_ERROR;
  1601. }
  1602. //----------------------------------------------------------------------------
  1603. // Function: MprConfigInterfaceCreate
  1604. //
  1605. // Creates a router-interface in the router-service store.
  1606. //----------------------------------------------------------------------------
  1607. DWORD APIENTRY
  1608. MprConfigInterfaceCreate(
  1609. IN HANDLE hMprConfig,
  1610. IN DWORD dwLevel,
  1611. IN LPBYTE lpbBuffer,
  1612. OUT HANDLE* phRouterInterface
  1613. )
  1614. {
  1615. INT cmp;
  1616. DWORD dwErr;
  1617. SERVERCB *pserver;
  1618. INTERFACECB* pinterface;
  1619. LIST_ENTRY *ple, *phead;
  1620. DWORD dwDialoutHoursRestrictionLength = 0;
  1621. MPR_INTERFACE_0 * pMprIf0 = (MPR_INTERFACE_0 *)lpbBuffer;
  1622. MPR_INTERFACE_1 * pMprIf1 = (MPR_INTERFACE_1 *)lpbBuffer;
  1623. if (( ( dwLevel != 0 ) && ( dwLevel != 1 ) ) ||
  1624. !lpbBuffer ||
  1625. !phRouterInterface) {return ERROR_INVALID_PARAMETER;}
  1626. //
  1627. // As of Whistler, ipip tunnels are not supported
  1628. //
  1629. if ( pMprIf0->dwIfType == ROUTER_IF_TYPE_TUNNEL1 )
  1630. {
  1631. return NO_ERROR;
  1632. }
  1633. *phRouterInterface = NULL;
  1634. pserver = (SERVERCB*)hMprConfig;
  1635. dwErr = MprConfigServerValidateCb(pserver);
  1636. if (dwErr != NO_ERROR)
  1637. {
  1638. return dwErr;
  1639. }
  1640. AcquireMprConfigLock();
  1641. //
  1642. // If the list of interfaces is not loaded, load it
  1643. //
  1644. if (!pserver->bInterfacesLoaded ||
  1645. TimeStampChanged(
  1646. pserver->hkeyInterfaces, &pserver->ftInterfacesStamp)) {
  1647. dwErr = LoadInterfaces(pserver);
  1648. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  1649. pserver->bInterfacesLoaded = TRUE;
  1650. }
  1651. //
  1652. // Search the list of interfaces for the one to be created
  1653. //
  1654. cmp = 1;
  1655. pinterface = NULL;
  1656. phead = &pserver->lhInterfaces;
  1657. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  1658. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  1659. if (pinterface->bDeleted) { continue; }
  1660. cmp = lstrcmpi( pinterface->lpwsInterfaceName,
  1661. pMprIf0->wszInterfaceName);
  1662. if (cmp >= 0) { break; }
  1663. }
  1664. //
  1665. // If the interface already exists, return
  1666. //
  1667. if (pinterface && cmp == 0) {
  1668. *phRouterInterface = (HANDLE)pinterface;
  1669. ReleaseMprConfigLock();
  1670. return NO_ERROR;
  1671. }
  1672. //
  1673. // Allocate a new context block
  1674. //
  1675. pinterface = (INTERFACECB*)Malloc(sizeof(*pinterface));
  1676. if (!pinterface) {
  1677. ReleaseMprConfigLock();
  1678. return ERROR_NOT_ENOUGH_MEMORY;
  1679. }
  1680. do {
  1681. WCHAR *lpwsKey, wszKey[12];
  1682. DWORD dwDisposition, dwKeyCount;
  1683. //
  1684. // Initialize the interface context
  1685. //
  1686. ZeroMemory(pinterface, sizeof(*pinterface));
  1687. InitializeListHead(&pinterface->lhIfTransports);
  1688. pinterface->dwIfType = (DWORD)pMprIf0->dwIfType;
  1689. pinterface->fEnabled = (BOOL)pMprIf0->fEnabled;
  1690. if ( ( pMprIf0->dwIfType == ROUTER_IF_TYPE_DEDICATED ) ||
  1691. ( pMprIf0->dwIfType == ROUTER_IF_TYPE_INTERNAL ) )
  1692. {
  1693. if ( !pMprIf0->fEnabled )
  1694. {
  1695. dwErr = ERROR_INVALID_PARAMETER;
  1696. break;
  1697. }
  1698. }
  1699. //
  1700. // Set dialout hours restriction if there was one
  1701. //
  1702. pinterface->lpwsDialoutHoursRestriction = NULL;
  1703. if ( dwLevel == 1 )
  1704. {
  1705. if ( pMprIf1->lpwsDialoutHoursRestriction != NULL )
  1706. {
  1707. dwDialoutHoursRestrictionLength =
  1708. MprUtilGetSizeOfMultiSz(
  1709. pMprIf1->lpwsDialoutHoursRestriction
  1710. );
  1711. pinterface->lpwsDialoutHoursRestriction =
  1712. (LPWSTR)Malloc(dwDialoutHoursRestrictionLength);
  1713. if ( pinterface->lpwsDialoutHoursRestriction == NULL )
  1714. {
  1715. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1716. break;
  1717. }
  1718. CopyMemory(
  1719. pinterface->lpwsDialoutHoursRestriction,
  1720. pMprIf1->lpwsDialoutHoursRestriction,
  1721. dwDialoutHoursRestrictionLength
  1722. );
  1723. }
  1724. }
  1725. //
  1726. // Make a copy of the interface name
  1727. //
  1728. pinterface->lpwsInterfaceName = StrDupW(pMprIf0->wszInterfaceName);
  1729. if (!pinterface->lpwsInterfaceName) {
  1730. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1731. break;
  1732. }
  1733. //
  1734. // If the server doesn't have the Interfaces key open, create it
  1735. //
  1736. if (!pserver->hkeyInterfaces) {
  1737. dwErr = AccessRouterSubkey(
  1738. pserver->hkeyMachine, c_szInterfaces, TRUE,
  1739. &pserver->hkeyInterfaces
  1740. );
  1741. if (dwErr != NO_ERROR) { break; }
  1742. }
  1743. //
  1744. // We need to select a unique key-name for the interface's key.
  1745. // We do so by getting the number 'N' of subkeys under 'Interfaces',
  1746. // then checking for the existence of a key whose name
  1747. // is the string-value of 'N'; if such a key exists, increment 'N'
  1748. // and try again.
  1749. //
  1750. dwErr = RegQueryInfoKey(
  1751. pserver->hkeyInterfaces, NULL, NULL, NULL, &dwKeyCount,
  1752. NULL, NULL, NULL, NULL, NULL, NULL, NULL
  1753. );
  1754. if (dwErr != NO_ERROR) { break; }
  1755. for ( ; ; ++dwKeyCount) {
  1756. //
  1757. // Convert the count to a string
  1758. //
  1759. wsprintf(wszKey, L"%d", dwKeyCount);
  1760. //
  1761. // Attempt to create a key with the resulting name;
  1762. //
  1763. dwErr = RegCreateKeyEx(
  1764. pserver->hkeyInterfaces, wszKey, 0, NULL, 0,
  1765. KEY_READ | KEY_WRITE | DELETE, NULL, &pinterface->hkey, &dwDisposition
  1766. );
  1767. if (dwErr != NO_ERROR) { break; }
  1768. //
  1769. // See if the key was created
  1770. //
  1771. if (dwDisposition == REG_CREATED_NEW_KEY) {
  1772. //
  1773. // We found a unique key-name;
  1774. //
  1775. break;
  1776. }
  1777. else {
  1778. //
  1779. // This key-name is already taken; clean up and keep looking.
  1780. //
  1781. RegCloseKey(pinterface->hkey);
  1782. pinterface->hkey = NULL;
  1783. }
  1784. }
  1785. if (dwErr != NO_ERROR) { break; }
  1786. //
  1787. // So far, so good; put the context in the list of interfaces;
  1788. // (the search done above told us the insertion point)
  1789. //
  1790. InsertTailList(ple, &pinterface->leNode);
  1791. //
  1792. // At this point a new key has been created for the interface,
  1793. // so update our timestamp on the 'Interfaces' key.
  1794. //
  1795. UpdateTimeStamp(pserver->hkeyInterfaces, &pserver->ftInterfacesStamp);
  1796. //
  1797. // Now we need to save the name of the key for the interface,
  1798. // and write the 'InterfaceName' and 'Type' into the registry.
  1799. // In the case of a failure, the interface's key needs to be removed,
  1800. // and we do so by invoking 'MprConfigInterfaceDelete'.
  1801. //
  1802. do {
  1803. //
  1804. // Duplicate the key-name for the interface
  1805. //
  1806. pinterface->lpwsInterfaceKey = StrDupW(wszKey);
  1807. if (!pinterface->lpwsInterfaceKey) {
  1808. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1809. break;
  1810. }
  1811. //
  1812. // Save the interface name
  1813. //
  1814. dwErr = RegSetValueEx(
  1815. pinterface->hkey, c_szInterfaceName, 0, REG_SZ,
  1816. (BYTE*)pMprIf0->wszInterfaceName,
  1817. (lstrlen(pMprIf0->wszInterfaceName) + 1) * sizeof(WCHAR)
  1818. );
  1819. if (dwErr != NO_ERROR) { break; }
  1820. //
  1821. // Save the interface type
  1822. //
  1823. dwErr = RegSetValueEx(
  1824. pinterface->hkey, c_szType, 0, REG_DWORD,
  1825. (BYTE*)&(pMprIf0->dwIfType),
  1826. sizeof(pMprIf0->dwIfType)
  1827. );
  1828. if (dwErr != NO_ERROR) { break; }
  1829. //
  1830. // Save the enabled state
  1831. //
  1832. dwErr = RegSetValueEx(
  1833. pinterface->hkey, c_szEnabled, 0, REG_DWORD,
  1834. (BYTE*)&(pMprIf0->fEnabled),
  1835. sizeof(pMprIf0->fEnabled)
  1836. );
  1837. if (dwErr != NO_ERROR) { break; }
  1838. if ( dwLevel == 1 )
  1839. {
  1840. if ( pMprIf1->lpwsDialoutHoursRestriction != NULL )
  1841. {
  1842. //
  1843. // Set dialout hours restriction if there was one
  1844. //
  1845. dwErr = RegSetValueEx(
  1846. pinterface->hkey, c_szDialoutHours, 0, REG_MULTI_SZ,
  1847. (BYTE*)pMprIf1->lpwsDialoutHoursRestriction,
  1848. dwDialoutHoursRestrictionLength
  1849. );
  1850. if (dwErr != NO_ERROR) { break; }
  1851. }
  1852. }
  1853. } while (FALSE);
  1854. //
  1855. // If a failure occurred, remove everything and bail out
  1856. //
  1857. if (dwErr != NO_ERROR) {
  1858. MprConfigInterfaceDelete(hMprConfig, (HANDLE)pinterface);
  1859. ReleaseMprConfigLock();
  1860. return dwErr;
  1861. }
  1862. //
  1863. // Clean out the guidmap
  1864. //
  1865. GuidMapCleanup (pserver->hGuidMap, FALSE);
  1866. //
  1867. // Return successfully
  1868. //
  1869. *phRouterInterface = (HANDLE)pinterface;
  1870. ReleaseMprConfigLock();
  1871. return NO_ERROR;
  1872. } while (FALSE);
  1873. //
  1874. // Something went wrong, so return
  1875. //
  1876. FreeInterface(pinterface);
  1877. ReleaseMprConfigLock();
  1878. return dwErr;
  1879. }
  1880. //----------------------------------------------------------------------------
  1881. // Function: MprConfigInterfaceDelete
  1882. //
  1883. // Deletes a router-interface from the router-service store.
  1884. // After this call, 'hRouterInterface' is no longer a valid handle.
  1885. // Any router-transport interface handles retrieved for this interface
  1886. // are also invalid.
  1887. //----------------------------------------------------------------------------
  1888. DWORD APIENTRY
  1889. MprConfigInterfaceDelete(
  1890. IN HANDLE hMprConfig,
  1891. IN HANDLE hRouterInterface
  1892. )
  1893. {
  1894. DWORD dwErr;
  1895. SERVERCB* pserver;
  1896. INTERFACECB* pinterface;
  1897. if (!hRouterInterface) { return ERROR_INVALID_PARAMETER; }
  1898. pserver = (SERVERCB*)hMprConfig;
  1899. dwErr = MprConfigServerValidateCb(pserver);
  1900. if (dwErr != NO_ERROR)
  1901. {
  1902. return dwErr;
  1903. }
  1904. AcquireMprConfigLock();
  1905. pinterface = (INTERFACECB*)hRouterInterface;
  1906. //
  1907. // remove the interface from the list of interfaces
  1908. //
  1909. RemoveEntryList(&pinterface->leNode);
  1910. //
  1911. // if the server doesn't have the Interfaces key open, open it
  1912. //
  1913. dwErr = NO_ERROR;
  1914. if (!pserver->hkeyInterfaces) {
  1915. dwErr = AccessRouterSubkey(
  1916. pserver->hkeyMachine, c_szInterfaces, FALSE,
  1917. &pserver->hkeyInterfaces
  1918. );
  1919. }
  1920. //
  1921. // remove the interface's key from the registry
  1922. //
  1923. if (dwErr == NO_ERROR) {
  1924. dwErr = RegDeleteTree(
  1925. pserver->hkeyInterfaces, pinterface->lpwsInterfaceKey
  1926. );
  1927. //
  1928. // We've deleted a subkey of the 'Interfaces' key,
  1929. // so update the time-stamp.
  1930. //
  1931. UpdateTimeStamp(pserver->hkeyInterfaces, &pserver->ftInterfacesStamp);
  1932. }
  1933. //
  1934. // clean up the interface object
  1935. //
  1936. FreeInterface(pinterface);
  1937. //
  1938. // Clean out the guidmap
  1939. //
  1940. GuidMapCleanup (pserver->hGuidMap, FALSE);
  1941. ReleaseMprConfigLock();
  1942. return dwErr;
  1943. }
  1944. //----------------------------------------------------------------------------
  1945. // Function: MprConfigInterfaceGetHandle
  1946. //
  1947. // Retrieves a handle to the interface configuration.
  1948. //----------------------------------------------------------------------------
  1949. DWORD APIENTRY
  1950. MprConfigInterfaceGetHandle(
  1951. IN HANDLE hMprConfig,
  1952. IN LPWSTR lpwsInterfaceName,
  1953. OUT HANDLE* phRouterInterface
  1954. )
  1955. {
  1956. INT cmp;
  1957. DWORD i, dwErr;
  1958. SERVERCB *pserver;
  1959. INTERFACECB* pinterface;
  1960. LIST_ENTRY *ple, *phead;
  1961. if (!hMprConfig || !phRouterInterface) {return ERROR_INVALID_PARAMETER;}
  1962. *phRouterInterface = NULL;
  1963. pserver = (SERVERCB*)hMprConfig;
  1964. dwErr = MprConfigServerValidateCb(pserver);
  1965. if (dwErr != NO_ERROR)
  1966. {
  1967. return dwErr;
  1968. }
  1969. AcquireMprConfigLock();
  1970. //
  1971. // If the list of interfaces is not loaded, load it
  1972. //
  1973. if (!pserver->bInterfacesLoaded ||
  1974. TimeStampChanged(
  1975. pserver->hkeyInterfaces, &pserver->ftInterfacesStamp)) {
  1976. dwErr = LoadInterfaces(pserver);
  1977. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  1978. pserver->bInterfacesLoaded = TRUE;
  1979. }
  1980. //
  1981. // Search the list of interfaces for the one requested
  1982. //
  1983. cmp = 1;
  1984. pinterface = NULL;
  1985. phead = &pserver->lhInterfaces;
  1986. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  1987. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  1988. if (pinterface->bDeleted) { continue; }
  1989. cmp = lstrcmpi(pinterface->lpwsInterfaceName, lpwsInterfaceName);
  1990. if (cmp >= 0) { break; }
  1991. }
  1992. //
  1993. // If the interface requested was found, return successfully
  1994. //
  1995. if (pinterface && cmp == 0) {
  1996. *phRouterInterface = (HANDLE)pinterface;
  1997. ReleaseMprConfigLock();
  1998. return NO_ERROR;
  1999. }
  2000. ReleaseMprConfigLock();
  2001. return ERROR_NO_SUCH_INTERFACE;
  2002. }
  2003. //----------------------------------------------------------------------------
  2004. // Function: MprConfigInterfaceGetInfo
  2005. //
  2006. // Retrieves information for an interface.
  2007. //----------------------------------------------------------------------------
  2008. DWORD
  2009. MprConfigInterfaceGetInfo(
  2010. IN HANDLE hMprConfig,
  2011. IN HANDLE hRouterInterface,
  2012. IN DWORD dwLevel,
  2013. IN OUT LPBYTE* lplpBuffer, // MPR_INTERFACE_*
  2014. OUT LPDWORD lpdwBufferSize
  2015. )
  2016. {
  2017. DWORD dwErr;
  2018. SERVERCB* pserver;
  2019. INTERFACECB* pinterface;
  2020. MPR_INTERFACE_0 *pItem;
  2021. DWORD dwDialoutHoursRestrictionLength = 0;
  2022. BOOL bInstalled;
  2023. if (!hRouterInterface ||
  2024. ((dwLevel != 0) && (dwLevel != 1)) ||
  2025. !lplpBuffer ||
  2026. !lpdwBufferSize) { return ERROR_INVALID_PARAMETER; }
  2027. pserver = (SERVERCB*)hMprConfig;
  2028. dwErr = MprConfigServerValidateCb(pserver);
  2029. if (dwErr != NO_ERROR)
  2030. {
  2031. return dwErr;
  2032. }
  2033. AcquireMprConfigLock();
  2034. pinterface = (INTERFACECB*)hRouterInterface;
  2035. *lplpBuffer = NULL;
  2036. *lpdwBufferSize = 0;
  2037. if (pinterface->bDeleted)
  2038. {
  2039. ReleaseMprConfigLock();
  2040. return ERROR_NO_SUCH_INTERFACE;
  2041. }
  2042. //
  2043. // Compute the amount of memory required for the information
  2044. //
  2045. if (dwLevel == 0) {
  2046. *lpdwBufferSize = sizeof( MPR_INTERFACE_0 );
  2047. }
  2048. else
  2049. if (dwLevel == 1) {
  2050. if ((pinterface->dwIfType == ROUTER_IF_TYPE_DEDICATED) ||
  2051. (pinterface->dwIfType == ROUTER_IF_TYPE_INTERNAL)) {
  2052. ReleaseMprConfigLock();
  2053. return ERROR_INVALID_PARAMETER;
  2054. }
  2055. dwDialoutHoursRestrictionLength =
  2056. MprUtilGetSizeOfMultiSz(
  2057. pinterface->lpwsDialoutHoursRestriction
  2058. );
  2059. *lpdwBufferSize =
  2060. sizeof(MPR_INTERFACE_1) + dwDialoutHoursRestrictionLength;
  2061. }
  2062. //
  2063. // Allocate space for the information
  2064. //
  2065. pItem = (MPR_INTERFACE_0*)Malloc( *lpdwBufferSize );
  2066. if (!pItem) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  2067. ZeroMemory(pItem, *lpdwBufferSize );
  2068. //
  2069. // Copy the requested interface-info from the context block
  2070. //
  2071. if (dwLevel == 0 || dwLevel == 1) {
  2072. lstrcpyn(
  2073. pItem->wszInterfaceName, pinterface->lpwsInterfaceName,
  2074. MAX_INTERFACE_NAME_LEN + 1
  2075. );
  2076. pItem->hInterface = (HANDLE)pinterface;
  2077. pItem->dwIfType = (ROUTER_INTERFACE_TYPE)pinterface->dwIfType;
  2078. pItem->fEnabled = pinterface->fEnabled;
  2079. //
  2080. // Indicate any pnp info that we have if it's a LAN adpt.
  2081. //
  2082. if (pinterface->dwIfType == ROUTER_IF_TYPE_DEDICATED)
  2083. {
  2084. bInstalled = FALSE;
  2085. dwErr = GuidMapIsAdapterInstalled(
  2086. pserver->hGuidMap,
  2087. pinterface->lpwsInterfaceName,
  2088. &bInstalled);
  2089. if (!bInstalled)
  2090. {
  2091. pItem->dwConnectionState = ROUTER_IF_STATE_UNREACHABLE;
  2092. pItem->fUnReachabilityReasons |= MPR_INTERFACE_NO_DEVICE;
  2093. }
  2094. }
  2095. }
  2096. if (dwLevel == 1) {
  2097. MPR_INTERFACE_1 *pItem1 = (MPR_INTERFACE_1 *)pItem;
  2098. if (pinterface->lpwsDialoutHoursRestriction) {
  2099. CopyMemory(
  2100. pItem1 + 1,
  2101. pinterface->lpwsDialoutHoursRestriction,
  2102. dwDialoutHoursRestrictionLength
  2103. );
  2104. pItem1->lpwsDialoutHoursRestriction =
  2105. (LPWSTR)(pItem1 + 1);
  2106. }
  2107. }
  2108. *lplpBuffer = (LPBYTE)pItem;
  2109. ReleaseMprConfigLock();
  2110. return NO_ERROR;
  2111. }
  2112. //----------------------------------------------------------------------------
  2113. // Function: MprConfigInterfaceSetInfo
  2114. //
  2115. // Changes the configuration for an interface.
  2116. //----------------------------------------------------------------------------
  2117. DWORD APIENTRY
  2118. MprConfigInterfaceSetInfo(
  2119. IN HANDLE hMprConfig,
  2120. IN HANDLE hRouterInterface,
  2121. IN DWORD dwLevel,
  2122. IN LPBYTE lpBuffer
  2123. )
  2124. {
  2125. DWORD dwErr;
  2126. SERVERCB* pserver;
  2127. INTERFACECB* pinterface;
  2128. MPR_INTERFACE_0 * pMprIf0 = (MPR_INTERFACE_0 *)lpBuffer;
  2129. //
  2130. // Validate parameters
  2131. //
  2132. if (!lpBuffer ||
  2133. ((dwLevel != 0) && (dwLevel != 1)) ||
  2134. !hRouterInterface) { return ERROR_INVALID_PARAMETER; }
  2135. pserver = (SERVERCB*)hMprConfig;
  2136. dwErr = MprConfigServerValidateCb(pserver);
  2137. if (dwErr != NO_ERROR)
  2138. {
  2139. return dwErr;
  2140. }
  2141. AcquireMprConfigLock();
  2142. pinterface = (INTERFACECB*)hRouterInterface;
  2143. if (pinterface->bDeleted) {
  2144. ReleaseMprConfigLock();
  2145. return ERROR_NO_SUCH_INTERFACE;
  2146. }
  2147. do {
  2148. if (dwLevel == 0 || dwLevel == 1) {
  2149. if ((pMprIf0->dwIfType == ROUTER_IF_TYPE_DEDICATED) ||
  2150. (pMprIf0->dwIfType == ROUTER_IF_TYPE_INTERNAL)) {
  2151. if (!pMprIf0->fEnabled) {
  2152. dwErr = ERROR_INVALID_PARAMETER;
  2153. break;
  2154. }
  2155. }
  2156. //
  2157. // Set the enabled value
  2158. //
  2159. dwErr = RegSetValueEx(
  2160. pinterface->hkey, c_szEnabled, 0, REG_DWORD,
  2161. (LPBYTE)&pMprIf0->fEnabled, sizeof(pMprIf0->fEnabled)
  2162. );
  2163. if (dwErr != NO_ERROR) { break; }
  2164. pinterface->fEnabled = pMprIf0->fEnabled;
  2165. }
  2166. if (dwLevel == 1) {
  2167. MPR_INTERFACE_1 * pMprIf1 = (MPR_INTERFACE_1 *)lpBuffer;
  2168. LPWSTR lpwsDialoutHoursRestriction;
  2169. DWORD dwDialoutHoursRestrictionLength = 0;
  2170. if ((pinterface->dwIfType == ROUTER_IF_TYPE_DEDICATED) ||
  2171. (pinterface->dwIfType == ROUTER_IF_TYPE_INTERNAL)) {
  2172. dwErr = ERROR_INVALID_PARAMETER; break;
  2173. }
  2174. //
  2175. // Set or remove the value
  2176. //
  2177. if (!pMprIf1->lpwsDialoutHoursRestriction) {
  2178. dwErr = RegDeleteValue(pinterface->hkey, c_szDialoutHours);
  2179. }
  2180. else {
  2181. dwDialoutHoursRestrictionLength =
  2182. MprUtilGetSizeOfMultiSz(
  2183. pMprIf1->lpwsDialoutHoursRestriction
  2184. );
  2185. lpwsDialoutHoursRestriction =
  2186. (LPWSTR)Malloc(dwDialoutHoursRestrictionLength);
  2187. if (lpwsDialoutHoursRestriction == NULL) {
  2188. dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  2189. }
  2190. CopyMemory(
  2191. lpwsDialoutHoursRestriction,
  2192. pMprIf1->lpwsDialoutHoursRestriction,
  2193. dwDialoutHoursRestrictionLength
  2194. );
  2195. //
  2196. // Set dialout hours restriction if there was one
  2197. //
  2198. dwErr = RegSetValueEx(
  2199. pinterface->hkey, c_szDialoutHours, 0, REG_MULTI_SZ,
  2200. (BYTE*)pMprIf1->lpwsDialoutHoursRestriction,
  2201. dwDialoutHoursRestrictionLength
  2202. );
  2203. }
  2204. if (dwErr != NO_ERROR) {Free0(lpwsDialoutHoursRestriction); break;}
  2205. //
  2206. // Cache the current value on success
  2207. //
  2208. Free0(pinterface->lpwsDialoutHoursRestriction);
  2209. pinterface->lpwsDialoutHoursRestriction =
  2210. lpwsDialoutHoursRestriction;
  2211. }
  2212. dwErr = NO_ERROR;
  2213. } while(FALSE);
  2214. ReleaseMprConfigLock();
  2215. return dwErr;
  2216. }
  2217. //----------------------------------------------------------------------------
  2218. // Function: MprConfigInterfaceEnum
  2219. //
  2220. // Enumerates the configured router-interfaces.
  2221. //----------------------------------------------------------------------------
  2222. DWORD APIENTRY
  2223. MprConfigInterfaceEnum(
  2224. IN HANDLE hMprConfig,
  2225. IN DWORD dwLevel,
  2226. IN OUT LPBYTE* lplpBuffer,
  2227. IN DWORD dwPrefMaxLen,
  2228. OUT LPDWORD lpdwEntriesRead,
  2229. OUT LPDWORD lpdwTotalEntries,
  2230. IN OUT LPDWORD lpdwResumeHandle OPTIONAL
  2231. )
  2232. {
  2233. SERVERCB* pserver;
  2234. INTERFACECB* pinterface;
  2235. LIST_ENTRY *ple, *phead, *pleStart;
  2236. MPR_INTERFACE_0 *pItem, *pItemTable;
  2237. DWORD dwErr, i, dwStartIndex, dwItemCount, dwItemTotal;
  2238. if ((dwLevel != 0) ||
  2239. !lplpBuffer ||
  2240. dwPrefMaxLen < sizeof(*pItem) ||
  2241. !lpdwEntriesRead ||
  2242. !lpdwTotalEntries) { return ERROR_INVALID_PARAMETER; }
  2243. pserver = (SERVERCB*)hMprConfig;
  2244. dwErr = MprConfigServerValidateCb(pserver);
  2245. if (dwErr != NO_ERROR)
  2246. {
  2247. return dwErr;
  2248. }
  2249. AcquireMprConfigLock();
  2250. *lplpBuffer = NULL;
  2251. *lpdwEntriesRead = 0;
  2252. *lpdwTotalEntries = 0;
  2253. //
  2254. // See whether the enumeration is being continued or being begun.
  2255. //
  2256. if (lpdwResumeHandle && *lpdwResumeHandle) {
  2257. //
  2258. // A resumption handle is specified,
  2259. // so we assume that our list of interfaces is up-to-date,
  2260. // and we just count off the requested number of interfaces
  2261. // from our list starting from the specified index.
  2262. //
  2263. dwStartIndex = *lpdwResumeHandle;
  2264. }
  2265. else {
  2266. //
  2267. // No resumption handle was specified, so we may need to read
  2268. // all the interfaces in order to get 'lpdwTotalEntries'
  2269. //
  2270. dwStartIndex = 0;
  2271. if (!pserver->bInterfacesLoaded ||
  2272. TimeStampChanged(
  2273. pserver->hkeyInterfaces, &pserver->ftInterfacesStamp)) {
  2274. dwErr = LoadInterfaces(pserver);
  2275. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  2276. pserver->bInterfacesLoaded = TRUE;
  2277. }
  2278. }
  2279. //
  2280. // Find the position in the list to start from
  2281. //
  2282. phead = &pserver->lhInterfaces;
  2283. for (i = 0, ple = phead->Flink;
  2284. i < dwStartIndex && ple != phead; ple = ple->Flink) {
  2285. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  2286. if (!pinterface->bDeleted) { ++i; }
  2287. }
  2288. //
  2289. // If there aren't enough items to complete the request, fail
  2290. //
  2291. if (ple == phead) { ReleaseMprConfigLock(); return ERROR_NO_MORE_ITEMS; }
  2292. pleStart = ple;
  2293. //
  2294. // Count off the number of items requested
  2295. //
  2296. dwItemCount = dwPrefMaxLen / sizeof(*pItemTable);
  2297. for (i = 0; i < dwItemCount && ple != phead; ple = ple->Flink) {
  2298. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  2299. if (!pinterface->bDeleted) { ++i; }
  2300. }
  2301. dwItemCount = i;
  2302. //
  2303. // Finish counting off, to get the total number of items
  2304. //
  2305. for ( ; ple != phead; ple = ple->Flink) {
  2306. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  2307. if (!pinterface->bDeleted) { ++i; }
  2308. }
  2309. dwItemTotal = i;
  2310. //
  2311. // We now have the number of items to be retrieved, so allocate space
  2312. //
  2313. pItemTable = (MPR_INTERFACE_0*)Malloc(dwItemCount * sizeof(*pItem));
  2314. if (!pItemTable) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  2315. ZeroMemory(pItemTable, dwItemCount * sizeof(*pItem));
  2316. //
  2317. // Now fill in the items using the listed interface objects
  2318. //
  2319. for (i = 0, ple = pleStart; i < dwItemCount; ple = ple->Flink) {
  2320. //
  2321. // Get the next interface-object in our list
  2322. //
  2323. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  2324. if (pinterface->bDeleted) { continue; }
  2325. //
  2326. // fill in information for the corresponding array item
  2327. //
  2328. pItem = pItemTable + i++;
  2329. lstrcpyn(
  2330. pItem->wszInterfaceName, pinterface->lpwsInterfaceName,
  2331. MAX_INTERFACE_NAME_LEN + 1
  2332. );
  2333. pItem->hInterface = (HANDLE)pinterface;
  2334. pItem->dwIfType = (ROUTER_INTERFACE_TYPE)pinterface->dwIfType;
  2335. pItem->fEnabled = pinterface->fEnabled;
  2336. }
  2337. *lplpBuffer = (LPBYTE)pItemTable;
  2338. *lpdwEntriesRead = dwItemCount;
  2339. *lpdwTotalEntries = dwItemTotal;
  2340. if (lpdwResumeHandle) { *lpdwResumeHandle = dwStartIndex + dwItemCount; }
  2341. ReleaseMprConfigLock();
  2342. return NO_ERROR;
  2343. }
  2344. //----------------------------------------------------------------------------
  2345. // Function: MprConfigInterfaceTransportAdd
  2346. //
  2347. // Adds a router-transport to a router-interface in the store.
  2348. //----------------------------------------------------------------------------
  2349. DWORD APIENTRY
  2350. MprConfigInterfaceTransportAdd(
  2351. IN HANDLE hMprConfig,
  2352. IN HANDLE hRouterInterface,
  2353. IN DWORD dwTransportId,
  2354. IN LPWSTR lpwsTransportName OPTIONAL,
  2355. IN LPBYTE pInterfaceInfo,
  2356. IN DWORD dwInterfaceInfoSize,
  2357. OUT HANDLE* phRouterIfTransport
  2358. )
  2359. {
  2360. DWORD dwErr;
  2361. SERVERCB *pserver;
  2362. INTERFACECB* pinterface;
  2363. IFTRANSPORTCB* piftransport;
  2364. LIST_ENTRY *ple, *phead;
  2365. if (!hRouterInterface ||
  2366. !phRouterIfTransport) { return ERROR_INVALID_PARAMETER; }
  2367. *phRouterIfTransport = NULL;
  2368. pserver = (SERVERCB*)hMprConfig;
  2369. dwErr = MprConfigServerValidateCb(pserver);
  2370. if (dwErr != NO_ERROR)
  2371. {
  2372. return dwErr;
  2373. }
  2374. AcquireMprConfigLock();
  2375. pinterface = (INTERFACECB*)hRouterInterface;
  2376. //
  2377. // If the list of interface-transports is not loaded, load it
  2378. //
  2379. if (!pinterface->bIfTransportsLoaded ||
  2380. TimeStampChanged(pinterface->hkey, &pinterface->ftStamp)) {
  2381. dwErr = LoadIfTransports(pinterface);
  2382. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  2383. pinterface->bIfTransportsLoaded = TRUE;
  2384. }
  2385. //
  2386. // Search the list of interface-transports for the one to be created
  2387. //
  2388. piftransport = NULL;
  2389. phead = &pinterface->lhIfTransports;
  2390. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  2391. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2392. if (piftransport->bDeleted) { continue; }
  2393. if (piftransport->dwTransportId >= dwTransportId) { break; }
  2394. }
  2395. //
  2396. // If the transport already exists, do a SetInfo instead
  2397. //
  2398. if (piftransport && piftransport->dwTransportId == dwTransportId) {
  2399. DWORD dwErr2;
  2400. *phRouterIfTransport = (HANDLE)piftransport;
  2401. dwErr2 = MprConfigInterfaceTransportSetInfo(
  2402. hMprConfig,
  2403. hRouterInterface,
  2404. *phRouterIfTransport,
  2405. pInterfaceInfo,
  2406. dwInterfaceInfoSize
  2407. );
  2408. ReleaseMprConfigLock();
  2409. return dwErr2;
  2410. }
  2411. //
  2412. // Allocate a new context block
  2413. //
  2414. piftransport = (IFTRANSPORTCB*)Malloc(sizeof(*piftransport));
  2415. if (!piftransport) {
  2416. ReleaseMprConfigLock();
  2417. return ERROR_NOT_ENOUGH_MEMORY;
  2418. }
  2419. do {
  2420. DWORD dwDisposition;
  2421. const WCHAR *lpwsKey;
  2422. WCHAR wszIfTransport[10];
  2423. //
  2424. // Initialize the transport context
  2425. //
  2426. ZeroMemory(piftransport, sizeof(*piftransport));
  2427. piftransport->dwTransportId = dwTransportId;
  2428. //
  2429. // If the transport name is specified, use it as the key name;
  2430. // otherwise, if it is a recognized transport, use a known name;
  2431. // otherwise, convert the transport ID to a string and use that
  2432. //
  2433. if (lpwsTransportName && lstrlen(lpwsTransportName)) {
  2434. lpwsKey = lpwsTransportName;
  2435. }
  2436. else
  2437. if (dwTransportId == PID_IP) {
  2438. lpwsKey = c_szIP;
  2439. }
  2440. else
  2441. if (dwTransportId == PID_IPX) {
  2442. lpwsKey = c_szIPX;
  2443. }
  2444. else {
  2445. wsprintf(wszIfTransport, L"%d", dwTransportId);
  2446. lpwsKey = wszIfTransport;
  2447. }
  2448. piftransport->lpwsIfTransportKey = StrDupW(lpwsKey);
  2449. if (!piftransport->lpwsIfTransportKey) {
  2450. dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  2451. }
  2452. //
  2453. // Create a key for the interface-transport in the registry
  2454. //
  2455. dwErr = RegCreateKeyEx(
  2456. pinterface->hkey, lpwsKey, 0, NULL, 0,
  2457. KEY_READ | KEY_WRITE | DELETE, NULL, &piftransport->hkey, &dwDisposition
  2458. );
  2459. if (dwErr != NO_ERROR) { break; }
  2460. //
  2461. // Update the timestamp on the interface's key
  2462. // now that a new subkey has been created under it.
  2463. //
  2464. UpdateTimeStamp(pinterface->hkey, &pinterface->ftStamp);
  2465. //
  2466. // Set the "ProtocolId" value for the interface transport
  2467. //
  2468. dwErr = RegSetValueEx(
  2469. piftransport->hkey, c_szProtocolId, 0, REG_DWORD,
  2470. (LPBYTE)&dwTransportId, sizeof(dwTransportId)
  2471. );
  2472. //
  2473. // So far, so good; put the context in the list of interface-transports;
  2474. // (the search done above told us the insertion point)
  2475. //
  2476. InsertTailList(ple, &piftransport->leNode);
  2477. //
  2478. // Now call SetInfo to save the information
  2479. //
  2480. dwErr = MprConfigInterfaceTransportSetInfo(
  2481. hMprConfig,
  2482. hRouterInterface,
  2483. (HANDLE)piftransport,
  2484. pInterfaceInfo,
  2485. dwInterfaceInfoSize
  2486. );
  2487. //
  2488. // If that failed, remove everything and bail out
  2489. //
  2490. if (dwErr != NO_ERROR) {
  2491. MprConfigInterfaceTransportRemove(
  2492. hMprConfig,
  2493. hRouterInterface,
  2494. (HANDLE)piftransport
  2495. );
  2496. ReleaseMprConfigLock();
  2497. return dwErr;
  2498. }
  2499. //
  2500. // Return successfully
  2501. //
  2502. *phRouterIfTransport = (HANDLE)piftransport;
  2503. ReleaseMprConfigLock();
  2504. return NO_ERROR;
  2505. } while (FALSE);
  2506. //
  2507. // Something went wrong, so return
  2508. //
  2509. FreeIfTransport(piftransport);
  2510. ReleaseMprConfigLock();
  2511. return dwErr;
  2512. }
  2513. //----------------------------------------------------------------------------
  2514. // Function: MprConfigInterfaceTransportRemove
  2515. //
  2516. // Removes a router-transport from a router-interface in the store.
  2517. // After this call, 'hRouterIfTransport' is no longer a valid handle.
  2518. //----------------------------------------------------------------------------
  2519. DWORD APIENTRY
  2520. MprConfigInterfaceTransportRemove(
  2521. IN HANDLE hMprConfig,
  2522. IN HANDLE hRouterInterface,
  2523. IN HANDLE hRouterIfTransport
  2524. )
  2525. {
  2526. DWORD dwErr;
  2527. SERVERCB* pserver;
  2528. INTERFACECB* pinterface;
  2529. IFTRANSPORTCB* piftransport;
  2530. if (!hMprConfig ||
  2531. !hRouterInterface ||
  2532. !hRouterIfTransport) { return ERROR_INVALID_PARAMETER; }
  2533. pserver = (SERVERCB*)hMprConfig;
  2534. dwErr = MprConfigServerValidateCb(pserver);
  2535. if (dwErr != NO_ERROR)
  2536. {
  2537. return dwErr;
  2538. }
  2539. AcquireMprConfigLock();
  2540. pinterface = (INTERFACECB*)hRouterInterface;
  2541. piftransport = (IFTRANSPORTCB*)hRouterIfTransport;
  2542. //
  2543. // remove the interface-transport from the list of interface-transports
  2544. //
  2545. RemoveEntryList(&piftransport->leNode);
  2546. //
  2547. // remove the transport's key from the registry
  2548. //
  2549. dwErr = RegDeleteTree(
  2550. pinterface->hkey, piftransport->lpwsIfTransportKey
  2551. );
  2552. //
  2553. // Update the timestamp on the interface's key
  2554. // now that a subkey has been deleted from under it.
  2555. //
  2556. UpdateTimeStamp(pinterface->hkey, &pinterface->ftStamp);
  2557. //
  2558. // clean up the transport object
  2559. //
  2560. FreeIfTransport(piftransport);
  2561. ReleaseMprConfigLock();
  2562. return dwErr;
  2563. }
  2564. //----------------------------------------------------------------------------
  2565. // Function: MprConfigInterfaceTransportGetHandle
  2566. //
  2567. // Retrieves a handle to a router-transport's interface configuration.
  2568. //----------------------------------------------------------------------------
  2569. DWORD APIENTRY
  2570. MprConfigInterfaceTransportGetHandle(
  2571. IN HANDLE hMprConfig,
  2572. IN HANDLE hRouterInterface,
  2573. IN DWORD dwTransportId,
  2574. OUT HANDLE* phRouterIfTransport
  2575. )
  2576. {
  2577. DWORD i, dwErr;
  2578. SERVERCB *pserver;
  2579. INTERFACECB* pinterface;
  2580. IFTRANSPORTCB* piftransport;
  2581. LIST_ENTRY *ple, *phead;
  2582. if (!hRouterInterface ||
  2583. !phRouterIfTransport) { return ERROR_INVALID_PARAMETER; }
  2584. *phRouterIfTransport = NULL;
  2585. pserver = (SERVERCB*)hMprConfig;
  2586. dwErr = MprConfigServerValidateCb(pserver);
  2587. if (dwErr != NO_ERROR)
  2588. {
  2589. return dwErr;
  2590. }
  2591. AcquireMprConfigLock();
  2592. pinterface = (INTERFACECB*)hRouterInterface;
  2593. if (pinterface->bDeleted) {
  2594. ReleaseMprConfigLock();
  2595. return ERROR_NO_SUCH_INTERFACE;
  2596. }
  2597. //
  2598. // If the list of interface-transports is not loaded, load it
  2599. //
  2600. if (!pinterface->bIfTransportsLoaded ||
  2601. TimeStampChanged(pinterface->hkey, &pinterface->ftStamp)) {
  2602. dwErr = LoadIfTransports(pinterface);
  2603. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  2604. pinterface->bIfTransportsLoaded = TRUE;
  2605. }
  2606. //
  2607. // Search the list of interface-transports for the one requested
  2608. //
  2609. piftransport = NULL;
  2610. phead = &pinterface->lhIfTransports;
  2611. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  2612. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2613. if (piftransport->bDeleted) { continue; }
  2614. if (piftransport->dwTransportId >= dwTransportId) { break; }
  2615. }
  2616. //
  2617. // If the interface-transport requested was found, return successfully
  2618. //
  2619. if (piftransport && piftransport->dwTransportId == dwTransportId) {
  2620. *phRouterIfTransport = (HANDLE)piftransport;
  2621. ReleaseMprConfigLock();
  2622. return NO_ERROR;
  2623. }
  2624. ReleaseMprConfigLock();
  2625. return ERROR_NO_SUCH_INTERFACE;
  2626. }
  2627. //----------------------------------------------------------------------------
  2628. // Function: MprConfigInterfaceTransportGetInfo
  2629. //
  2630. // Reads the configuration of a router-transport for a router-interface.
  2631. //----------------------------------------------------------------------------
  2632. DWORD APIENTRY
  2633. MprConfigInterfaceTransportGetInfo(
  2634. IN HANDLE hMprConfig,
  2635. IN HANDLE hRouterInterface,
  2636. IN HANDLE hRouterIfTransport,
  2637. IN OUT LPBYTE* ppInterfaceInfo,
  2638. OUT LPDWORD lpdwInterfaceInfoSize
  2639. )
  2640. {
  2641. DWORD dwErr;
  2642. SERVERCB* pserver;
  2643. INTERFACECB* pinterface;
  2644. IFTRANSPORTCB* piftransport;
  2645. //
  2646. // Validate parameters
  2647. //
  2648. if (!hRouterInterface ||
  2649. !hRouterIfTransport) { return ERROR_INVALID_PARAMETER; }
  2650. if (!ppInterfaceInfo) { return NO_ERROR; }
  2651. if (ppInterfaceInfo &&
  2652. !lpdwInterfaceInfoSize) { return ERROR_INVALID_PARAMETER; }
  2653. //
  2654. // Initialize all parameters
  2655. //
  2656. if (ppInterfaceInfo) { *ppInterfaceInfo = NULL; }
  2657. if (lpdwInterfaceInfoSize) { *lpdwInterfaceInfoSize = 0; }
  2658. pserver = (SERVERCB*)hMprConfig;
  2659. dwErr = MprConfigServerValidateCb(pserver);
  2660. if (dwErr != NO_ERROR)
  2661. {
  2662. return dwErr;
  2663. }
  2664. AcquireMprConfigLock();
  2665. pinterface = (INTERFACECB*)hRouterInterface;
  2666. piftransport = (IFTRANSPORTCB*)hRouterIfTransport;
  2667. if (pinterface->bDeleted || piftransport->bDeleted) {
  2668. ReleaseMprConfigLock();
  2669. return ERROR_NO_SUCH_INTERFACE;
  2670. }
  2671. do {
  2672. DWORD dwType, dwSize;
  2673. //
  2674. // Retrieve the interface info
  2675. //
  2676. if (ppInterfaceInfo) {
  2677. dwErr = QueryValue(
  2678. piftransport->hkey, c_szInterfaceInfo, ppInterfaceInfo,
  2679. lpdwInterfaceInfoSize
  2680. );
  2681. if (dwErr != NO_ERROR) { break; }
  2682. }
  2683. //
  2684. // All went well, return successfully
  2685. //
  2686. ReleaseMprConfigLock();
  2687. return NO_ERROR;
  2688. } while(FALSE);
  2689. //
  2690. // An error occurred, free all parameters and return failure
  2691. //
  2692. if (ppInterfaceInfo) {
  2693. Free0(*ppInterfaceInfo);
  2694. *ppInterfaceInfo = NULL; *lpdwInterfaceInfoSize = 0;
  2695. }
  2696. ReleaseMprConfigLock();
  2697. return dwErr;
  2698. }
  2699. //----------------------------------------------------------------------------
  2700. // Function: MprConfigInterfaceTransportSetInfo
  2701. //
  2702. // Changes the configuration of a router-transport for a router-interface.
  2703. //----------------------------------------------------------------------------
  2704. DWORD APIENTRY
  2705. MprConfigInterfaceTransportSetInfo(
  2706. IN HANDLE hMprConfig,
  2707. IN HANDLE hRouterInterface,
  2708. IN HANDLE hRouterIfTransport,
  2709. IN LPBYTE pInterfaceInfo OPTIONAL,
  2710. IN DWORD dwInterfaceInfoSize OPTIONAL
  2711. )
  2712. {
  2713. DWORD dwErr;
  2714. SERVERCB* pserver;
  2715. INTERFACECB* pinterface;
  2716. IFTRANSPORTCB* piftransport;
  2717. //
  2718. // Validate parameters
  2719. //
  2720. if (!hRouterInterface ||
  2721. !hRouterIfTransport) { return ERROR_INVALID_PARAMETER; }
  2722. if (!pInterfaceInfo) { return NO_ERROR; }
  2723. pserver = (SERVERCB*)hMprConfig;
  2724. dwErr = MprConfigServerValidateCb(pserver);
  2725. if (dwErr != NO_ERROR)
  2726. {
  2727. return dwErr;
  2728. }
  2729. AcquireMprConfigLock();
  2730. pinterface = (INTERFACECB*)hRouterInterface;
  2731. piftransport = (IFTRANSPORTCB*)hRouterIfTransport;
  2732. if (pinterface->bDeleted || piftransport->bDeleted) {
  2733. ReleaseMprConfigLock();
  2734. return ERROR_NO_SUCH_INTERFACE;
  2735. }
  2736. do {
  2737. //
  2738. // Set the InterfaceInfo
  2739. //
  2740. if (pInterfaceInfo) {
  2741. dwErr = RegSetValueEx(
  2742. piftransport->hkey, c_szInterfaceInfo, 0, REG_BINARY,
  2743. pInterfaceInfo, dwInterfaceInfoSize
  2744. );
  2745. if (dwErr != NO_ERROR) { break; }
  2746. }
  2747. dwErr = NO_ERROR;
  2748. } while(FALSE);
  2749. ReleaseMprConfigLock();
  2750. return dwErr;
  2751. }
  2752. //----------------------------------------------------------------------------
  2753. // Function: MprConfigInterfaceTransportEnum
  2754. //
  2755. // Enumerates the transports configured on a router-interface.
  2756. //----------------------------------------------------------------------------
  2757. DWORD APIENTRY
  2758. MprConfigInterfaceTransportEnum(
  2759. IN HANDLE hMprConfig,
  2760. IN HANDLE hRouterInterface,
  2761. IN DWORD dwLevel,
  2762. IN OUT LPBYTE* lplpBuffer, // MPR_IFTRANSPORT_0
  2763. IN DWORD dwPrefMaxLen,
  2764. OUT LPDWORD lpdwEntriesRead,
  2765. OUT LPDWORD lpdwTotalEntries,
  2766. IN OUT LPDWORD lpdwResumeHandle OPTIONAL
  2767. )
  2768. {
  2769. SERVERCB* pserver;
  2770. INTERFACECB* pinterface;
  2771. IFTRANSPORTCB* piftransport;
  2772. LIST_ENTRY *ple, *phead, *pleStart;
  2773. MPR_IFTRANSPORT_0 *pItem, *pItemTable;
  2774. DWORD dwErr, i, dwStartIndex, dwItemCount, dwItemTotal;
  2775. if (!hRouterInterface ||
  2776. (dwLevel != 0) ||
  2777. !lplpBuffer ||
  2778. dwPrefMaxLen < sizeof(*pItem) ||
  2779. !lpdwEntriesRead ||
  2780. !lpdwTotalEntries) { return ERROR_INVALID_PARAMETER; }
  2781. pserver = (SERVERCB*)hMprConfig;
  2782. dwErr = MprConfigServerValidateCb(pserver);
  2783. if (dwErr != NO_ERROR)
  2784. {
  2785. return dwErr;
  2786. }
  2787. AcquireMprConfigLock();
  2788. pinterface = (INTERFACECB*)hRouterInterface;
  2789. *lplpBuffer = NULL;
  2790. *lpdwEntriesRead = 0;
  2791. *lpdwTotalEntries = 0;
  2792. //
  2793. // See whether the enumeration is being continued or being begun.
  2794. //
  2795. if (lpdwResumeHandle && *lpdwResumeHandle) {
  2796. //
  2797. // A resumption handle is specified,
  2798. // so we assume that our list of transports is up-to-date,
  2799. // and we just count off the requested number of transports
  2800. // from our list starting from the specified index.
  2801. //
  2802. dwStartIndex = *lpdwResumeHandle;
  2803. }
  2804. else {
  2805. //
  2806. // No resumption handle was specified, so we may need to read
  2807. // all the interface-transports in order to get 'lpdwTotalEntries'
  2808. //
  2809. dwStartIndex = 0;
  2810. if (!pinterface->bIfTransportsLoaded ||
  2811. TimeStampChanged(pinterface->hkey, &pinterface->ftStamp)) {
  2812. dwErr = LoadIfTransports(pinterface);
  2813. if (dwErr != NO_ERROR) { ReleaseMprConfigLock(); return dwErr; }
  2814. pinterface->bIfTransportsLoaded = TRUE;
  2815. }
  2816. }
  2817. //
  2818. // Find the position in the list to start from
  2819. //
  2820. phead = &pinterface->lhIfTransports;
  2821. for (i = 0, ple = phead->Flink;
  2822. i < dwStartIndex && ple != phead; ple = ple->Flink) {
  2823. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2824. if (!piftransport->bDeleted) { ++i; }
  2825. }
  2826. //
  2827. // If there aren't enough items to complete the request, fail
  2828. //
  2829. if (ple == phead) { ReleaseMprConfigLock(); return ERROR_NO_MORE_ITEMS; }
  2830. pleStart = ple;
  2831. //
  2832. // Count off the number of items requested
  2833. //
  2834. dwItemCount = dwPrefMaxLen / sizeof(*pItemTable);
  2835. for (i = 0; i < dwItemCount && ple != phead; ple = ple->Flink) {
  2836. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2837. if (!piftransport->bDeleted) { ++i; }
  2838. }
  2839. dwItemCount = i;
  2840. //
  2841. // Finish counting off, to get the total number of items
  2842. //
  2843. for ( ; ple != phead; ple = ple->Flink) {
  2844. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2845. if (!piftransport->bDeleted) { ++i; }
  2846. }
  2847. dwItemTotal = i;
  2848. //
  2849. // We now have the number of items to be retrieved, so allocate space
  2850. //
  2851. pItemTable = (MPR_IFTRANSPORT_0*)Malloc(dwItemCount * sizeof(*pItem));
  2852. if (!pItemTable) { ReleaseMprConfigLock(); return ERROR_NOT_ENOUGH_MEMORY; }
  2853. ZeroMemory(pItemTable, dwItemCount * sizeof(*pItem));
  2854. //
  2855. // Now fill in the items using the listed interface-transport objects
  2856. //
  2857. for (i = 0, ple = pleStart; i < dwItemCount; ple = ple->Flink) {
  2858. //
  2859. // Get the next interface-transport object in our list
  2860. //
  2861. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  2862. if (piftransport->bDeleted) { continue; }
  2863. //
  2864. // Fill in information for the corresponding array item
  2865. //
  2866. pItem = pItemTable + i++;
  2867. pItem->dwTransportId = piftransport->dwTransportId;
  2868. pItem->hIfTransport = (HANDLE)piftransport;
  2869. if (piftransport->lpwsIfTransportKey) {
  2870. lstrcpyn(
  2871. pItem->wszIfTransportName, piftransport->lpwsIfTransportKey,
  2872. MAX_TRANSPORT_NAME_LEN + 1
  2873. );
  2874. }
  2875. }
  2876. *lplpBuffer = (LPBYTE)pItemTable;
  2877. *lpdwEntriesRead = dwItemCount;
  2878. *lpdwTotalEntries = dwItemTotal;
  2879. if (lpdwResumeHandle) { *lpdwResumeHandle = dwStartIndex + dwItemCount; }
  2880. ReleaseMprConfigLock();
  2881. return NO_ERROR;
  2882. }
  2883. //----------------------------------------------------------------------------
  2884. // Function: MprConfigGetFriendlyName
  2885. //
  2886. // Returns a friendly name based on a guid name.
  2887. //----------------------------------------------------------------------------
  2888. DWORD APIENTRY
  2889. MprConfigGetFriendlyName(
  2890. IN HANDLE hMprConfig,
  2891. IN PWCHAR pszGuidName,
  2892. OUT PWCHAR pszBuffer,
  2893. IN DWORD dwBufferSize
  2894. )
  2895. {
  2896. SERVERCB* pserver = (SERVERCB*)hMprConfig;
  2897. DWORD dwErr;
  2898. dwErr = MprConfigServerValidateCb(pserver);
  2899. if (dwErr != NO_ERROR)
  2900. {
  2901. return dwErr;
  2902. }
  2903. //
  2904. // Validate parameters
  2905. //
  2906. if (!pszGuidName || !pszBuffer) {
  2907. return ERROR_INVALID_PARAMETER;
  2908. }
  2909. AcquireMprConfigLock();
  2910. //
  2911. // Return the mapping
  2912. //
  2913. dwErr =
  2914. GuidMapGetFriendlyName(
  2915. pserver,
  2916. pszGuidName,
  2917. dwBufferSize,
  2918. pszBuffer
  2919. );
  2920. ReleaseMprConfigLock();
  2921. return dwErr;
  2922. }
  2923. //----------------------------------------------------------------------------
  2924. // Function: MprConfigGetGuidName
  2925. //
  2926. // Returns a guid name based on a friendly name.
  2927. //----------------------------------------------------------------------------
  2928. DWORD APIENTRY
  2929. MprConfigGetGuidName(
  2930. IN HANDLE hMprConfig,
  2931. IN PWCHAR pszFriendlyName,
  2932. OUT PWCHAR pszBuffer,
  2933. IN DWORD dwBufferSize
  2934. )
  2935. {
  2936. SERVERCB* pserver = (SERVERCB*)hMprConfig;
  2937. DWORD dwErr;
  2938. dwErr = MprConfigServerValidateCb(pserver);
  2939. if (dwErr != NO_ERROR)
  2940. {
  2941. return dwErr;
  2942. }
  2943. // Validate parameters
  2944. if (!pszFriendlyName || !pszBuffer) {
  2945. return ERROR_INVALID_PARAMETER;
  2946. }
  2947. AcquireMprConfigLock();
  2948. // Return the mapping
  2949. dwErr = GuidMapGetGuidName(
  2950. pserver,
  2951. pszFriendlyName,
  2952. dwBufferSize,
  2953. pszBuffer
  2954. );
  2955. ReleaseMprConfigLock();
  2956. return dwErr;
  2957. }
  2958. //----------------------------------------------------------------------------
  2959. // Function: AccessRouterSubkey
  2960. //
  2961. // Creates/opens a subkey of the Router service key on 'hkeyMachine'.
  2962. // When a key is created, 'lpwsSubkey' must be a child of the Router key.
  2963. //----------------------------------------------------------------------------
  2964. DWORD
  2965. AccessRouterSubkey(
  2966. IN HKEY hkeyMachine,
  2967. IN LPCWSTR lpwsSubkey,
  2968. IN BOOL bCreate,
  2969. OUT HKEY* phkeySubkey
  2970. )
  2971. {
  2972. HKEY hkeyRouter;
  2973. LPWSTR lpwsPath;
  2974. DWORD dwErr, dwSize, dwDisposition;
  2975. BOOL bIsNt40;
  2976. if (!phkeySubkey) { return ERROR_INVALID_PARAMETER; }
  2977. *phkeySubkey = NULL;
  2978. //
  2979. // Find out whether we are adminstrating an nt40 machine as this will
  2980. // affect the path we take in the registry.
  2981. //
  2982. if ((dwErr = IsNt40Machine(hkeyMachine, &bIsNt40)) != NO_ERROR) {
  2983. return dwErr;
  2984. }
  2985. //
  2986. // compute the length of the string "System\CCS\Services\RemoteAccess"
  2987. //
  2988. if (bIsNt40) {
  2989. dwSize = lstrlen(c_szSystemCCSServices) + 1 + lstrlen(c_szRouter) + 1;
  2990. }
  2991. else {
  2992. dwSize =
  2993. lstrlen(c_szSystemCCSServices) + 1 + lstrlen(c_szRemoteAccess) + 1;
  2994. }
  2995. //
  2996. // allocate space for the path
  2997. //
  2998. lpwsPath = (LPWSTR)Malloc(dwSize * sizeof(WCHAR));
  2999. if (!lpwsPath) { return ERROR_NOT_ENOUGH_MEMORY; }
  3000. if (bIsNt40) {
  3001. wsprintf(lpwsPath, L"%s\\%s", c_szSystemCCSServices, c_szRouter);
  3002. }
  3003. else {
  3004. wsprintf(lpwsPath, L"%s\\%s", c_szSystemCCSServices, c_szRemoteAccess);
  3005. }
  3006. hkeyRouter = NULL;
  3007. do {
  3008. //
  3009. // open the router key
  3010. //
  3011. dwErr = RegOpenKeyEx(
  3012. hkeyMachine, lpwsPath, 0, KEY_READ | KEY_WRITE, &hkeyRouter
  3013. );
  3014. if (dwErr != NO_ERROR) { break; }
  3015. //
  3016. // now create or open the specified subkey
  3017. //
  3018. if (!bCreate) {
  3019. dwErr = RegOpenKeyEx(
  3020. hkeyRouter, lpwsSubkey, 0, KEY_READ | KEY_WRITE, phkeySubkey
  3021. );
  3022. }
  3023. else {
  3024. dwErr = RegCreateKeyEx(
  3025. hkeyRouter, lpwsSubkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
  3026. NULL, phkeySubkey, &dwDisposition
  3027. );
  3028. }
  3029. } while(FALSE);
  3030. if (hkeyRouter) { RegCloseKey(hkeyRouter); }
  3031. Free(lpwsPath);
  3032. return dwErr;
  3033. }
  3034. //----------------------------------------------------------------------------
  3035. // Function: DeleteRegistryTree
  3036. //
  3037. // Delete the tree of registry values starting at hkRoot
  3038. //----------------------------------------------------------------------------
  3039. DWORD
  3040. DeleteRegistryTree(
  3041. HKEY hkRoot
  3042. )
  3043. {
  3044. DWORD dwErr = NO_ERROR;
  3045. DWORD dwCount, dwNameSize, dwDisposition, i, dwCurNameSize;
  3046. PWCHAR pszNameBuf;
  3047. HKEY hkTemp;
  3048. //
  3049. // Find out how many keys there are in the source
  3050. //
  3051. dwErr =
  3052. RegQueryInfoKey(
  3053. hkRoot, NULL,NULL,NULL, &dwCount, &dwNameSize, NULL, NULL, NULL,
  3054. NULL, NULL, NULL
  3055. );
  3056. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  3057. dwNameSize++;
  3058. do
  3059. {
  3060. //
  3061. // Allocate the buffers
  3062. //
  3063. pszNameBuf = (PWCHAR)Malloc(dwNameSize * sizeof(WCHAR));
  3064. if (!pszNameBuf)
  3065. {
  3066. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  3067. break;
  3068. }
  3069. //
  3070. // Loop through the keys -- deleting all subkey trees
  3071. //
  3072. for (i = 0; i < dwCount; i++) {
  3073. dwCurNameSize = dwNameSize;
  3074. //
  3075. // Get the current source key
  3076. //
  3077. dwErr =
  3078. RegEnumKeyExW(
  3079. hkRoot, i, pszNameBuf, &dwCurNameSize, 0, NULL, NULL, NULL
  3080. );
  3081. if (dwErr != ERROR_SUCCESS) { continue; }
  3082. //
  3083. // Open the subkey
  3084. //
  3085. dwErr =
  3086. RegCreateKeyExW(
  3087. hkRoot, pszNameBuf, 0, NULL, REG_OPTION_NON_VOLATILE,
  3088. KEY_READ | KEY_WRITE | DELETE, NULL, &hkTemp, &dwDisposition
  3089. );
  3090. if (dwErr != ERROR_SUCCESS) { continue; }
  3091. //
  3092. // Delete the subkey tree
  3093. //
  3094. DeleteRegistryTree(hkTemp);
  3095. //
  3096. // Close the temp handle
  3097. //
  3098. RegCloseKey(hkTemp);
  3099. }
  3100. //
  3101. // Loop through the keys -- deleting all subkeys themselves
  3102. //
  3103. for (i = 0; i < dwCount; i++) {
  3104. dwCurNameSize = dwNameSize;
  3105. //
  3106. // Get the current source key
  3107. //
  3108. dwErr =
  3109. RegEnumKeyExW(
  3110. hkRoot, 0, pszNameBuf, &dwCurNameSize, 0, NULL, NULL, NULL
  3111. );
  3112. if (dwErr != ERROR_SUCCESS) { continue; }
  3113. //
  3114. // Delete the subkey tree
  3115. //
  3116. dwErr = RegDeleteKey(hkRoot, pszNameBuf);
  3117. }
  3118. dwErr = NO_ERROR;
  3119. } while (FALSE);
  3120. // Cleanup
  3121. {
  3122. if (pszNameBuf) { Free(pszNameBuf); }
  3123. }
  3124. return dwErr;
  3125. }
  3126. //----------------------------------------------------------------------------
  3127. // Function: EnableBackupPrivilege
  3128. //
  3129. // Enables/disables backup privilege for the current process.
  3130. //----------------------------------------------------------------------------
  3131. DWORD
  3132. EnableBackupPrivilege(
  3133. IN BOOL bEnable,
  3134. IN LPWSTR pszPrivilege
  3135. )
  3136. {
  3137. LUID luid;
  3138. HANDLE hToken = NULL;
  3139. TOKEN_PRIVILEGES tp;
  3140. BOOL bOk;
  3141. //
  3142. // We first have to try to get the token of the current
  3143. // thread since if it is impersonating, adjusting the
  3144. // privileges of the process will have no effect.
  3145. //
  3146. bOk =
  3147. OpenThreadToken(
  3148. GetCurrentThread(),
  3149. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE,
  3150. &hToken
  3151. );
  3152. if (bOk == FALSE) {
  3153. //
  3154. // There is no thread token -- open it up for the
  3155. // process instead.
  3156. //
  3157. OpenProcessToken(
  3158. GetCurrentProcess(),
  3159. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3160. &hToken
  3161. );
  3162. }
  3163. //
  3164. // Get the LUID of the privilege
  3165. //
  3166. if (!LookupPrivilegeValue(NULL, pszPrivilege, &luid)) {
  3167. DWORD dwErr = GetLastError();
  3168. if(NULL != hToken)
  3169. {
  3170. CloseHandle(hToken);
  3171. }
  3172. return dwErr;
  3173. }
  3174. //
  3175. // Adjust the token privileges
  3176. //
  3177. tp.PrivilegeCount = 1;
  3178. tp.Privileges[0].Luid = luid;
  3179. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3180. //
  3181. // Commit changes to the system
  3182. //
  3183. if (!AdjustTokenPrivileges(
  3184. hToken, !bEnable, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL
  3185. )) {
  3186. DWORD dwErr = GetLastError();
  3187. if(NULL != hToken)
  3188. {
  3189. CloseHandle(hToken);
  3190. }
  3191. return dwErr;
  3192. }
  3193. //
  3194. // Even if AdjustTokenPrivileges succeeded (see MSDN) you still
  3195. // need to verify success by calling GetLastError.
  3196. //
  3197. if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
  3198. {
  3199. if(NULL != hToken)
  3200. {
  3201. CloseHandle(hToken);
  3202. }
  3203. return ERROR_NOT_ALL_ASSIGNED;
  3204. }
  3205. if(NULL != hToken)
  3206. {
  3207. CloseHandle(hToken);
  3208. }
  3209. return NO_ERROR;
  3210. }
  3211. //----------------------------------------------------------------------------
  3212. // Function: EnumInterfaces
  3213. //
  3214. // Enumerates the interfaces in the given key and calls the given callback
  3215. // for each one.
  3216. //
  3217. //----------------------------------------------------------------------------
  3218. DWORD
  3219. EnumLanInterfaces (
  3220. IN SERVERCB* pserver,
  3221. IN HKEY hkInterfaces,
  3222. IN PENUMIFCALLBACKFUNC pCallback,
  3223. IN DWORD dwData
  3224. )
  3225. {
  3226. DWORD dwErr, dwType, dwTypeVal, dwSize, dwCount, i;
  3227. HKEY hkCurIf = NULL;
  3228. WCHAR pszKey[5], pszName[512], pszTranslation[512];
  3229. //
  3230. // Get the count of interfaces under this key
  3231. //
  3232. dwErr =
  3233. RegQueryInfoKey(
  3234. hkInterfaces, NULL, NULL, NULL, &dwCount, NULL, NULL, NULL, NULL,
  3235. NULL, NULL, NULL
  3236. );
  3237. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  3238. //
  3239. // Loop through the interfaces, changing names as needed
  3240. //
  3241. for (i = 0; i < dwCount; i++) {
  3242. //
  3243. // Get the key
  3244. //
  3245. wsprintfW(pszKey, L"%d", i);
  3246. dwErr = RegOpenKeyEx(hkInterfaces, pszKey, 0, KEY_READ | KEY_WRITE, &hkCurIf);
  3247. if (dwErr != ERROR_SUCCESS) { continue; }
  3248. //
  3249. // Call the callback if the type is correct
  3250. //
  3251. dwSize = sizeof (DWORD);
  3252. dwErr =
  3253. RegQueryValueEx(
  3254. hkCurIf, c_szType, NULL, &dwType, (LPBYTE)&dwTypeVal, &dwSize
  3255. );
  3256. if ((dwErr == ERROR_SUCCESS) &&
  3257. (dwTypeVal == ROUTER_IF_TYPE_DEDICATED)) {
  3258. (*pCallback)(pserver, hkCurIf, dwData);
  3259. }
  3260. //
  3261. // Close the key
  3262. //
  3263. RegCloseKey (hkCurIf);
  3264. }
  3265. return NO_ERROR;
  3266. }
  3267. //----------------------------------------------------------------------------
  3268. // Function: FormatServerNameForMprCfgApis
  3269. //
  3270. // Generates a standard server name for use in the MprConfig api's.
  3271. //
  3272. // The lpwsServerName member of the SERVERCB struct will be in the format
  3273. // returned by this function.
  3274. //
  3275. // If pszServer references the local machine, NULL is returned.
  3276. // Otherwise, a server name is returned in the form "\\<server>"
  3277. //
  3278. //----------------------------------------------------------------------------
  3279. DWORD
  3280. FormatServerNameForMprCfgApis(
  3281. IN PWCHAR pszServer,
  3282. OUT PWCHAR* ppszServer)
  3283. {
  3284. PWCHAR pszServerPlain = NULL, pszServerOut = NULL;
  3285. WCHAR pszBuffer[512];
  3286. DWORD dwSize;
  3287. BOOL bOk;
  3288. // Null or empty string is empty
  3289. //
  3290. if ((pszServer == NULL) || (*pszServer == L'\0'))
  3291. {
  3292. *ppszServer = NULL;
  3293. return NO_ERROR;
  3294. }
  3295. // Find out the name of the server
  3296. //
  3297. pszServerPlain = pszServer;
  3298. if (*pszServer == L'\\')
  3299. {
  3300. if ((*(pszServer + 2) == L'\\') || (*(pszServer + 2) == L'\0'))
  3301. {
  3302. return ERROR_BAD_FORMAT;
  3303. }
  3304. pszServerPlain = pszServer + 2;
  3305. }
  3306. // At this point, pszServerPlain is the name of a server.
  3307. // Find out the name of the local machine
  3308. //
  3309. dwSize = sizeof(pszBuffer) / sizeof(WCHAR);
  3310. bOk = GetComputerNameExW(ComputerNameNetBIOS, pszBuffer, &dwSize);
  3311. if (!bOk)
  3312. {
  3313. return GetLastError();
  3314. }
  3315. // If the referenced machine is the local machine, return NULL
  3316. //
  3317. if (lstrcmpi(pszServerPlain, pszBuffer) == 0)
  3318. {
  3319. *ppszServer = NULL;
  3320. return NO_ERROR;
  3321. }
  3322. // Otherwise, return a formatted remote server name
  3323. //
  3324. pszServerOut = (PWCHAR)
  3325. Malloc((2 + wcslen(pszServerPlain) + 1) * sizeof(WCHAR));
  3326. if (pszServerOut == NULL)
  3327. {
  3328. return ERROR_NOT_ENOUGH_MEMORY;
  3329. }
  3330. wcscpy(pszServerOut, L"\\\\");
  3331. wcscpy(pszServerOut + 2, pszServerPlain);
  3332. *ppszServer = pszServerOut;
  3333. return NO_ERROR;
  3334. }
  3335. //----------------------------------------------------------------------------
  3336. // Function: FreeIfTransport
  3337. //
  3338. // Frees the context for an interface-transport.
  3339. // Assumes the interface-transport is no longer in any list.
  3340. //----------------------------------------------------------------------------
  3341. VOID
  3342. FreeIfTransport(
  3343. IN IFTRANSPORTCB* piftransport
  3344. )
  3345. {
  3346. if (piftransport->hkey) { RegCloseKey(piftransport->hkey); }
  3347. Free0(piftransport->lpwsIfTransportKey);
  3348. Free(piftransport);
  3349. }
  3350. //----------------------------------------------------------------------------
  3351. // Function: FreeInterface
  3352. //
  3353. // Frees the context for an interface.
  3354. // Assumes the interface is no longer in the list of interfaces.
  3355. //----------------------------------------------------------------------------
  3356. VOID
  3357. FreeInterface(
  3358. IN INTERFACECB* pinterface
  3359. )
  3360. {
  3361. //
  3362. // clean up all the interface's transport objects
  3363. //
  3364. LIST_ENTRY *ple, *phead;
  3365. phead = &pinterface->lhIfTransports;
  3366. while (!IsListEmpty(phead)) {
  3367. //
  3368. // retrieve the next interface-transport object
  3369. //
  3370. IFTRANSPORTCB* piftransport;
  3371. ple = RemoveHeadList(phead);
  3372. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  3373. //
  3374. // clean up the interface-transport object
  3375. //
  3376. FreeIfTransport(piftransport);
  3377. }
  3378. //
  3379. // clean up the interface object
  3380. //
  3381. if (pinterface->hkey) { RegCloseKey(pinterface->hkey); }
  3382. Free0(pinterface->lpwsInterfaceKey);
  3383. Free0(pinterface->lpwsInterfaceName);
  3384. Free0(pinterface->lpwsDialoutHoursRestriction);
  3385. Free(pinterface);
  3386. }
  3387. //----------------------------------------------------------------------------
  3388. // Function: FreeTransport
  3389. //
  3390. // Frees the context for a transport.
  3391. // Assumes the transport is no longer in the list of transports.
  3392. //----------------------------------------------------------------------------
  3393. VOID
  3394. FreeTransport(
  3395. IN TRANSPORTCB* ptransport
  3396. )
  3397. {
  3398. if (ptransport->hkey) { RegCloseKey(ptransport->hkey); }
  3399. Free0(ptransport->lpwsTransportKey);
  3400. Free(ptransport);
  3401. }
  3402. //----------------------------------------------------------------------------
  3403. // Function: GetLocalMachine
  3404. //
  3405. // Retrieves the name of the local machine (e.g. "\\MACHINE").
  3406. // Assumes the string supplied can hold MAX_COMPUTERNAME_LENGTH + 3 characters.
  3407. //----------------------------------------------------------------------------
  3408. VOID
  3409. GetLocalMachine(
  3410. IN LPWSTR lpwszMachine
  3411. )
  3412. {
  3413. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  3414. lstrcpy(lpwszMachine, c_szUncPrefix);
  3415. GetComputerName(lpwszMachine + 2, &dwSize);
  3416. }
  3417. //----------------------------------------------------------------------------
  3418. // Function: IsNt40Machine
  3419. //
  3420. // Returns whether the given hkeyMachine belongs to an nt40 registry
  3421. //----------------------------------------------------------------------------
  3422. DWORD
  3423. IsNt40Machine (
  3424. IN HKEY hkeyMachine,
  3425. OUT PBOOL pbIsNt40
  3426. )
  3427. {
  3428. DWORD dwErr = NO_ERROR;
  3429. DWORD dwType = REG_SZ, dwLength = 64 * sizeof(WCHAR);
  3430. HKEY hkeyVersion;
  3431. WCHAR pszBuildNumber[64];
  3432. //
  3433. // Validate and initialize
  3434. //
  3435. if (!pbIsNt40) { return ERROR_INVALID_PARAMETER; }
  3436. *pbIsNt40 = FALSE;
  3437. //
  3438. // Open the windows version key
  3439. //
  3440. dwErr = RegOpenKeyEx(
  3441. hkeyMachine, c_szWinVersionPath, 0, KEY_READ, &hkeyVersion
  3442. );
  3443. if (dwErr != NO_ERROR) { return dwErr; }
  3444. do
  3445. {
  3446. //
  3447. // Read in the current version key
  3448. //
  3449. dwErr = RegQueryValueEx (
  3450. hkeyVersion, c_szCurrentBuildNumber, NULL, &dwType,
  3451. (BYTE*)pszBuildNumber, &dwLength
  3452. );
  3453. if (dwErr != NO_ERROR)
  3454. {
  3455. dwErr = NO_ERROR;
  3456. break;
  3457. }
  3458. if (lstrcmp (pszBuildNumber, c_szNt40BuildNumber) == 0)
  3459. {
  3460. *pbIsNt40 = TRUE;
  3461. }
  3462. } while (FALSE);
  3463. // Cleanup
  3464. {
  3465. RegCloseKey(hkeyVersion);
  3466. }
  3467. return dwErr;
  3468. }
  3469. //----------------------------------------------------------------------------
  3470. // Function: LoadIfTransports
  3471. //
  3472. // Loads all the transports added to an interface.
  3473. //----------------------------------------------------------------------------
  3474. DWORD
  3475. LoadIfTransports(
  3476. IN INTERFACECB* pinterface
  3477. )
  3478. {
  3479. LPWSTR lpwsKey;
  3480. HKEY hkeyIfTransport;
  3481. IFTRANSPORTCB* piftransport;
  3482. LIST_ENTRY *ple, *phead;
  3483. DWORD i, dwErr, dwProtocolId, dwKeyCount, dwMaxKeyLength, dwType, dwLength;
  3484. //
  3485. // Any subkey of the Interfaces\<interface> key with a 'ProtocolId' value
  3486. // is assumed to be a valid interface-transport.
  3487. // Begin by marking all interfaces as 'deleted'.
  3488. //
  3489. phead = &pinterface->lhIfTransports;
  3490. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3491. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  3492. piftransport->bDeleted = TRUE;
  3493. }
  3494. //
  3495. // Get information about the interface key
  3496. //
  3497. dwErr = RegQueryInfoKey(
  3498. pinterface->hkey, NULL, NULL, NULL, &dwKeyCount,
  3499. &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL
  3500. );
  3501. if (dwErr != NO_ERROR) { return dwErr; }
  3502. if (!dwKeyCount) { return NO_ERROR; }
  3503. //
  3504. // Allocate space to hold the key-names to be enumerated
  3505. //
  3506. lpwsKey = (LPWSTR)Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  3507. if (!lpwsKey) { return ERROR_NOT_ENOUGH_MEMORY; }
  3508. //
  3509. // Now enumerate the keys, creating interface-transport objects
  3510. // for each key which contains a 'ProtocolId' value
  3511. //
  3512. for (i = 0; i < dwKeyCount; i++) {
  3513. //
  3514. // Get the next key name
  3515. //
  3516. dwLength = dwMaxKeyLength + 1;
  3517. dwErr = RegEnumKeyEx(
  3518. pinterface->hkey, i, lpwsKey, &dwLength, NULL, NULL, NULL,
  3519. NULL
  3520. );
  3521. if (dwErr != NO_ERROR) { break; }
  3522. //
  3523. // Open the key
  3524. //
  3525. dwErr = RegOpenKeyEx(
  3526. pinterface->hkey, lpwsKey, 0, KEY_READ | KEY_WRITE | DELETE,
  3527. &hkeyIfTransport
  3528. );
  3529. if (dwErr != NO_ERROR) { continue; }
  3530. do {
  3531. //
  3532. // See if the ProtocolId is present
  3533. //
  3534. dwLength = sizeof(dwProtocolId);
  3535. dwErr = RegQueryValueEx(
  3536. hkeyIfTransport, c_szProtocolId, NULL, &dwType,
  3537. (BYTE*)&dwProtocolId, &dwLength
  3538. );
  3539. if (dwErr != NO_ERROR) { dwErr = NO_ERROR; break; }
  3540. //
  3541. // The ProtocolId is present;
  3542. // search for this interface-transport in the existing list
  3543. //
  3544. piftransport = NULL;
  3545. phead = &pinterface->lhIfTransports;
  3546. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3547. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  3548. if (piftransport->dwTransportId >= dwProtocolId) { break; }
  3549. }
  3550. //
  3551. // If we found the interface-transport in our list, continue
  3552. //
  3553. if (piftransport && piftransport->dwTransportId == dwProtocolId) {
  3554. piftransport->bDeleted = FALSE;
  3555. // Free up the old key, it may have been deleted
  3556. // (and readded).
  3557. if (piftransport->hkey)
  3558. RegCloseKey(piftransport->hkey);
  3559. piftransport->hkey = hkeyIfTransport; hkeyIfTransport = NULL;
  3560. dwErr = NO_ERROR; break;
  3561. }
  3562. //
  3563. // The interface-transport isn't listed; create an object for it
  3564. //
  3565. piftransport = Malloc(sizeof(*piftransport));
  3566. if (!piftransport) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  3567. ZeroMemory(piftransport, sizeof(*piftransport));
  3568. piftransport->dwTransportId = dwProtocolId;
  3569. //
  3570. // duplicate the name of the interface-transport's key
  3571. //
  3572. piftransport->lpwsIfTransportKey = StrDupW(lpwsKey);
  3573. if (!piftransport->lpwsIfTransportKey) {
  3574. Free(piftransport); dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  3575. }
  3576. piftransport->hkey = hkeyIfTransport; hkeyIfTransport = NULL;
  3577. //
  3578. // insert the interface-transport in the list;
  3579. // the above search supplied the point of insertion
  3580. //
  3581. InsertTailList(ple, &piftransport->leNode);
  3582. dwErr = NO_ERROR;
  3583. } while(FALSE);
  3584. if (hkeyIfTransport) { RegCloseKey(hkeyIfTransport); }
  3585. if (dwErr != NO_ERROR) { break; }
  3586. }
  3587. Free(lpwsKey);
  3588. //
  3589. // Remove all objects still marked for deletion
  3590. //
  3591. phead = &pinterface->lhIfTransports;
  3592. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3593. piftransport = CONTAINING_RECORD(ple, IFTRANSPORTCB, leNode);
  3594. if (!piftransport->bDeleted) { continue; }
  3595. //
  3596. // Clean up the object, adjusting the list-pointer back by one.
  3597. //
  3598. ple = ple->Blink; RemoveEntryList(&piftransport->leNode);
  3599. FreeIfTransport(piftransport);
  3600. }
  3601. UpdateTimeStamp(pinterface->hkey, &pinterface->ftStamp);
  3602. return dwErr;
  3603. }
  3604. //----------------------------------------------------------------------------
  3605. // Function: LoadInterfaces
  3606. //
  3607. // Loads all the interfaces.
  3608. //----------------------------------------------------------------------------
  3609. DWORD
  3610. LoadInterfaces(
  3611. IN SERVERCB* pserver
  3612. )
  3613. {
  3614. INT cmp;
  3615. LPWSTR lpwsKey;
  3616. HKEY hkeyInterface;
  3617. INTERFACECB* pinterface;
  3618. LIST_ENTRY *ple, *phead;
  3619. WCHAR wszInterface[MAX_INTERFACE_NAME_LEN+1];
  3620. DWORD i, dwErr, dwIfType, dwKeyCount, dwMaxKeyLength, dwType, dwLength;
  3621. BOOL fEnabled, fAdapterInstalled;
  3622. DWORD dwMaxValueLength;
  3623. LPBYTE lpBuffer = NULL;
  3624. //
  3625. // Any subkey of the Interfaces key which has a 'Type' value
  3626. // is assumed to be a valid interface.
  3627. // Begin by marking all interfaces as 'deleted'.
  3628. //
  3629. phead = &pserver->lhInterfaces;
  3630. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3631. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  3632. pinterface->bDeleted = TRUE;
  3633. }
  3634. //
  3635. // Open the Interfaces key if it is not already open
  3636. //
  3637. if (!pserver->hkeyInterfaces) {
  3638. //
  3639. // If we cannot open the Interfaces key, assume it doesn't exist
  3640. // and therefore that there are no interfaces.
  3641. //
  3642. dwErr = AccessRouterSubkey(
  3643. pserver->hkeyMachine, c_szInterfaces, FALSE,
  3644. &pserver->hkeyInterfaces
  3645. );
  3646. if (dwErr != NO_ERROR) { return NO_ERROR; }
  3647. }
  3648. //
  3649. // Get information about the Interfaces key;
  3650. // we need to know how many subkeys it has and the maximum length
  3651. // of all subkey-names
  3652. //
  3653. dwErr = RegQueryInfoKey(
  3654. pserver->hkeyInterfaces, NULL, NULL, NULL, &dwKeyCount,
  3655. &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL
  3656. );
  3657. if (dwErr != NO_ERROR) { return dwErr; }
  3658. if (!dwKeyCount) { return NO_ERROR; }
  3659. //
  3660. // allocate space to hold the key-names to be enumerated
  3661. //
  3662. lpwsKey = (LPWSTR)Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  3663. if (!lpwsKey) { return ERROR_NOT_ENOUGH_MEMORY; }
  3664. //
  3665. // Now we enumerate the keys, creating interface-objects
  3666. // for each key which contains a 'Type' value
  3667. //
  3668. for (i = 0; i < dwKeyCount; i++) {
  3669. //
  3670. // Get the next key name
  3671. //
  3672. dwLength = dwMaxKeyLength + 1;
  3673. dwErr = RegEnumKeyEx(
  3674. pserver->hkeyInterfaces, i, lpwsKey, &dwLength,
  3675. NULL, NULL, NULL, NULL
  3676. );
  3677. if (dwErr != NO_ERROR) { break; }
  3678. //
  3679. // Open the key
  3680. //
  3681. dwErr = RegOpenKeyEx(
  3682. pserver->hkeyInterfaces, lpwsKey, 0, KEY_READ | KEY_WRITE | DELETE,
  3683. &hkeyInterface
  3684. );
  3685. if (dwErr != NO_ERROR) { continue; }
  3686. do {
  3687. //
  3688. // See if the InterfaceName is present
  3689. //
  3690. dwLength = sizeof(wszInterface);
  3691. dwErr = RegQueryValueEx(
  3692. hkeyInterface, c_szInterfaceName, NULL, &dwType,
  3693. (BYTE*)wszInterface, &dwLength
  3694. );
  3695. if (dwErr != NO_ERROR) { dwErr = NO_ERROR; break; }
  3696. //
  3697. // See if the Type is present
  3698. //
  3699. dwLength = sizeof(dwIfType);
  3700. dwErr = RegQueryValueEx(
  3701. hkeyInterface, c_szType, NULL, &dwType,
  3702. (BYTE*)&dwIfType, &dwLength
  3703. );
  3704. if (dwErr != NO_ERROR) { dwErr = NO_ERROR; break; }
  3705. //
  3706. // As of Whistler, ipip tunnels are not supported
  3707. //
  3708. if ( dwIfType == ROUTER_IF_TYPE_TUNNEL1 )
  3709. {
  3710. break;
  3711. }
  3712. //
  3713. // See if the enabled is present
  3714. //
  3715. dwLength = sizeof(fEnabled);
  3716. dwErr = RegQueryValueEx(
  3717. hkeyInterface, c_szEnabled, NULL, &dwType,
  3718. (BYTE*)&fEnabled, &dwLength
  3719. );
  3720. if ( dwErr == ERROR_FILE_NOT_FOUND )
  3721. {
  3722. fEnabled = TRUE;
  3723. dwErr = NO_ERROR;
  3724. }
  3725. if (dwErr != NO_ERROR) { dwErr = NO_ERROR; break; }
  3726. //
  3727. // The InterfaceName and Type are present;
  3728. // search for this interface in the existing list
  3729. //
  3730. cmp = 1;
  3731. pinterface = NULL;
  3732. phead = &pserver->lhInterfaces;
  3733. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3734. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  3735. cmp = lstrcmpi(pinterface->lpwsInterfaceName, wszInterface);
  3736. if (cmp >= 0) { break; }
  3737. }
  3738. //
  3739. // If we found the interface in our list, continue
  3740. //
  3741. if (pinterface && cmp == 0) {
  3742. pinterface->bDeleted = FALSE;
  3743. dwErr = NO_ERROR;
  3744. // Use the new registry value (the old one may have
  3745. // been replaced).
  3746. if (pinterface->hkey)
  3747. RegCloseKey(pinterface->hkey);
  3748. pinterface->hkey = hkeyInterface; hkeyInterface = NULL;
  3749. }
  3750. else {
  3751. //
  3752. // The interface isn't in our list; create an object for it
  3753. //
  3754. pinterface = Malloc(sizeof(*pinterface));
  3755. if (!pinterface) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  3756. ZeroMemory(pinterface, sizeof(*pinterface));
  3757. //
  3758. // Duplicate the name of the interface's key
  3759. // as well as the name of the interface itself
  3760. //
  3761. pinterface->lpwsInterfaceKey = StrDupW(lpwsKey);
  3762. if (!pinterface->lpwsInterfaceKey) {
  3763. Free(pinterface); dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  3764. }
  3765. pinterface->lpwsInterfaceName = StrDupW(wszInterface);
  3766. if (!pinterface->lpwsInterfaceName) {
  3767. Free(pinterface->lpwsInterfaceKey);
  3768. Free(pinterface); dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  3769. }
  3770. pinterface->fEnabled = fEnabled;
  3771. pinterface->dwIfType = dwIfType;
  3772. pinterface->hkey = hkeyInterface; hkeyInterface = NULL;
  3773. InitializeListHead(&pinterface->lhIfTransports);
  3774. //
  3775. // insert the interface in the list;
  3776. // the above search supplied the point of insertion
  3777. //
  3778. InsertTailList(ple, &pinterface->leNode);
  3779. }
  3780. //
  3781. // Now read optional fields.
  3782. //
  3783. Free0(pinterface->lpwsDialoutHoursRestriction);
  3784. pinterface->lpwsDialoutHoursRestriction = NULL;
  3785. //
  3786. // Load the dial-out hours restriction value.
  3787. //
  3788. dwErr = RegQueryInfoKey(
  3789. pinterface->hkey, NULL, NULL, NULL, NULL,
  3790. NULL, NULL, NULL, NULL, &dwMaxValueLength, NULL, NULL
  3791. );
  3792. if (dwErr != NO_ERROR) { break; }
  3793. lpBuffer = Malloc(dwMaxValueLength);
  3794. if (!lpBuffer) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  3795. //
  3796. // Read the 'DialoutHours'
  3797. //
  3798. dwLength = dwMaxValueLength;
  3799. dwErr =
  3800. RegQueryValueEx(
  3801. pinterface->hkey, c_szDialoutHours, NULL, &dwType,
  3802. (BYTE*)lpBuffer, &dwLength
  3803. );
  3804. if (dwErr == NO_ERROR) {
  3805. pinterface->lpwsDialoutHoursRestriction =
  3806. (LPWSTR)Malloc(dwLength);
  3807. if (!pinterface->lpwsDialoutHoursRestriction) {
  3808. dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  3809. }
  3810. CopyMemory(
  3811. pinterface->lpwsDialoutHoursRestriction, lpBuffer, dwLength
  3812. );
  3813. }
  3814. dwErr = NO_ERROR;
  3815. } while(FALSE);
  3816. if (hkeyInterface) { RegCloseKey(hkeyInterface); }
  3817. Free0(lpBuffer); lpBuffer = NULL;
  3818. if (dwErr != NO_ERROR) { break; }
  3819. }
  3820. Free(lpwsKey);
  3821. //
  3822. // Clean up all objects still marked for deletion
  3823. //
  3824. phead = &pserver->lhInterfaces;
  3825. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3826. pinterface = CONTAINING_RECORD(ple, INTERFACECB, leNode);
  3827. if (pinterface->bDeleted) {
  3828. //
  3829. // Clean up the object, adjusting our list-pointer back by one.
  3830. //
  3831. ple = ple->Blink; RemoveEntryList(&pinterface->leNode);
  3832. FreeInterface(pinterface);
  3833. continue;
  3834. }
  3835. }
  3836. UpdateTimeStamp(pserver->hkeyInterfaces, &pserver->ftInterfacesStamp);
  3837. return dwErr;
  3838. }
  3839. //----------------------------------------------------------------------------
  3840. // Function: LoadParameters
  3841. //
  3842. // Loads all the parameters.
  3843. //----------------------------------------------------------------------------
  3844. DWORD
  3845. LoadParameters(
  3846. IN SERVERCB* pserver
  3847. )
  3848. {
  3849. LPWSTR lpwsKey;
  3850. DWORD dwErr, dwLength, dwType;
  3851. if (!pserver->hkeyParameters) {
  3852. dwErr = AccessRouterSubkey(
  3853. pserver->hkeyMachine, c_szParameters, FALSE,
  3854. &pserver->hkeyParameters
  3855. );
  3856. if (dwErr != NO_ERROR) { return NO_ERROR; }
  3857. }
  3858. dwLength = sizeof(pserver->fRouterType);
  3859. dwErr = RegQueryValueEx(
  3860. pserver->hkeyParameters, c_szRouterType, NULL, &dwType,
  3861. (BYTE*)&pserver->fRouterType, &dwLength
  3862. );
  3863. if (dwErr != NO_ERROR) { return dwErr; }
  3864. UpdateTimeStamp(pserver->hkeyParameters, &pserver->ftParametersStamp);
  3865. return NO_ERROR;
  3866. }
  3867. //----------------------------------------------------------------------------
  3868. // Function: LoadTransports
  3869. //
  3870. // Loads all the transports.
  3871. //----------------------------------------------------------------------------
  3872. DWORD
  3873. LoadTransports(
  3874. IN SERVERCB* pserver
  3875. )
  3876. {
  3877. LPWSTR lpwsKey;
  3878. HKEY hkeyTransport;
  3879. TRANSPORTCB* ptransport;
  3880. LIST_ENTRY *ple, *phead;
  3881. DWORD i, dwErr, dwKeyCount, dwMaxKeyLength, dwProtocolId, dwType, dwLength;
  3882. //
  3883. // Any subkey of the RouterManagers key which has a 'ProtocolId' value
  3884. // is assumed to be a valid transport.
  3885. // Begin by marking all transports as 'deleted'
  3886. //
  3887. phead = &pserver->lhTransports;
  3888. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3889. ptransport = CONTAINING_RECORD(ple,TRANSPORTCB, leNode);
  3890. ptransport->bDeleted = TRUE;
  3891. }
  3892. //
  3893. // We will enumerate by calling RegEnumKeyEx repeatedly,
  3894. // so open the transports key if it is not already open
  3895. //
  3896. if (!pserver->hkeyTransports) {
  3897. //
  3898. // If we cannot open the RouterManagers key, assume it doesn't exist
  3899. // and therefore that there are no transports.
  3900. //
  3901. dwErr = AccessRouterSubkey(
  3902. pserver->hkeyMachine, c_szRouterManagers, FALSE,
  3903. &pserver->hkeyTransports
  3904. );
  3905. if (dwErr != NO_ERROR) { return NO_ERROR; }
  3906. }
  3907. //
  3908. // Get information about the RouterManagers key;
  3909. // we need to know how many subkeys it has and
  3910. // the maximum length of all subkey-names
  3911. //
  3912. dwErr = RegQueryInfoKey(
  3913. pserver->hkeyTransports, NULL, NULL, NULL, &dwKeyCount,
  3914. &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL
  3915. );
  3916. if (dwErr != NO_ERROR) { return dwErr; }
  3917. if (!dwKeyCount) { return NO_ERROR; }
  3918. //
  3919. // allocate space to hold the key-names to be enumerated
  3920. //
  3921. lpwsKey = (LPWSTR)Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  3922. if (!lpwsKey) { return ERROR_NOT_ENOUGH_MEMORY; }
  3923. //
  3924. // Now we enumerate the keys, creating transport-objects
  3925. // for each key which contains a 'ProtocolId' value
  3926. //
  3927. for (i = 0; i < dwKeyCount; i++) {
  3928. //
  3929. // get the next key name
  3930. //
  3931. dwLength = dwMaxKeyLength + 1;
  3932. dwErr = RegEnumKeyEx(
  3933. pserver->hkeyTransports, i, lpwsKey, &dwLength,
  3934. NULL, NULL, NULL, NULL
  3935. );
  3936. if (dwErr != NO_ERROR) { break; }
  3937. //
  3938. // Open the key
  3939. //
  3940. dwErr = RegOpenKeyEx(
  3941. pserver->hkeyTransports, lpwsKey, 0, KEY_READ | KEY_WRITE | DELETE,
  3942. &hkeyTransport
  3943. );
  3944. if (dwErr != NO_ERROR) { continue; }
  3945. do {
  3946. //
  3947. // see if the protocol ID is present
  3948. //
  3949. dwLength = sizeof(dwProtocolId);
  3950. dwErr = RegQueryValueEx(
  3951. hkeyTransport, c_szProtocolId, NULL, &dwType,
  3952. (BYTE*)&dwProtocolId, &dwLength
  3953. );
  3954. if (dwErr != NO_ERROR) { dwErr = NO_ERROR; break; }
  3955. //
  3956. // the protocol ID is present;
  3957. // search for this protocol in the existing list
  3958. //
  3959. ptransport = NULL;
  3960. phead = &pserver->lhTransports;
  3961. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  3962. ptransport = CONTAINING_RECORD(ple,TRANSPORTCB, leNode);
  3963. if (ptransport->dwTransportId >= dwProtocolId) { break; }
  3964. }
  3965. //
  3966. // if we found the transport in our list, continue
  3967. //
  3968. if (ptransport && ptransport->dwTransportId == dwProtocolId) {
  3969. ptransport->bDeleted = FALSE;
  3970. // Use the new key, the old one may have been deleted
  3971. if (ptransport->hkey)
  3972. RegCloseKey(ptransport->hkey);
  3973. ptransport->hkey = hkeyTransport; hkeyTransport = NULL;
  3974. dwErr = NO_ERROR;
  3975. break;
  3976. }
  3977. //
  3978. // The transport isn't in our list; create an object for it
  3979. //
  3980. ptransport = Malloc(sizeof(*ptransport));
  3981. if (!ptransport) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  3982. ZeroMemory(ptransport, sizeof(*ptransport));
  3983. //
  3984. // duplicate the name of the transport's key
  3985. //
  3986. ptransport->lpwsTransportKey = StrDupW(lpwsKey);
  3987. if (!ptransport->lpwsTransportKey) {
  3988. Free(ptransport); dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
  3989. }
  3990. ptransport->dwTransportId = dwProtocolId;
  3991. ptransport->hkey = hkeyTransport; hkeyTransport = NULL;
  3992. //
  3993. // insert the transport in the list;
  3994. // the above search supplied the point of insertion
  3995. //
  3996. InsertTailList(ple, &ptransport->leNode);
  3997. dwErr = NO_ERROR;
  3998. } while(FALSE);
  3999. if (hkeyTransport) { RegCloseKey(hkeyTransport); }
  4000. if (dwErr != NO_ERROR) { break; }
  4001. }
  4002. Free(lpwsKey);
  4003. //
  4004. // Clean up all objects still marked for deletion
  4005. //
  4006. for (ple = phead->Flink; ple != phead; ple = ple->Flink) {
  4007. ptransport = CONTAINING_RECORD(ple, TRANSPORTCB, leNode);
  4008. if (!ptransport->bDeleted) { continue; }
  4009. //
  4010. // Clean up the object, adjusting our list-pointer back by one.
  4011. //
  4012. ple = ple->Blink; RemoveEntryList(&ptransport->leNode);
  4013. FreeTransport(ptransport);
  4014. }
  4015. UpdateTimeStamp(pserver->hkeyTransports, &pserver->ftTransportsStamp);
  4016. return dwErr;
  4017. }
  4018. //----------------------------------------------------------------------------
  4019. // Function: MapInterfaceNamesCb
  4020. //
  4021. // Changes the name of an interface
  4022. //----------------------------------------------------------------------------
  4023. DWORD
  4024. MapInterfaceNamesCb(
  4025. IN SERVERCB* pserver,
  4026. IN HKEY hkInterface,
  4027. IN DWORD dwData
  4028. )
  4029. {
  4030. WCHAR pszName[512], pszTranslation[512];
  4031. DWORD dwErr, dwType, dwSize;
  4032. //
  4033. // Map and change the name
  4034. //
  4035. dwSize = sizeof(pszName);
  4036. dwErr =
  4037. RegQueryValueEx(
  4038. hkInterface, c_szInterfaceName, NULL, &dwType, (LPBYTE)pszName,
  4039. &dwSize
  4040. );
  4041. if (dwErr == ERROR_SUCCESS) {
  4042. DWORD BufLen;
  4043. if (dwData) {
  4044. BufLen = sizeof(pszTranslation);
  4045. dwErr =
  4046. MprConfigGetFriendlyName(
  4047. (HANDLE)pserver,
  4048. pszName,
  4049. pszTranslation,
  4050. BufLen //pass number of bytes, Not chars
  4051. );
  4052. }
  4053. else {
  4054. BufLen = sizeof(pszTranslation);
  4055. dwErr =
  4056. MprConfigGetGuidName(
  4057. (HANDLE)pserver,
  4058. pszName,
  4059. pszTranslation,
  4060. BufLen //pass number of bytes, Not chars
  4061. );
  4062. }
  4063. if (dwErr == NO_ERROR) {
  4064. RegSetValueEx(
  4065. hkInterface,
  4066. c_szInterfaceName,
  4067. 0,
  4068. REG_SZ,
  4069. (CONST BYTE*)pszTranslation,
  4070. lstrlen(pszTranslation) * sizeof(WCHAR) + sizeof(WCHAR)
  4071. );
  4072. }
  4073. }
  4074. return NO_ERROR;
  4075. }
  4076. //----------------------------------------------------------------------------
  4077. // Function: QueryValue
  4078. //
  4079. // Queries the 'hkey' for the value 'lpwsValue', allocating memory
  4080. // for the resulting data
  4081. //----------------------------------------------------------------------------
  4082. DWORD
  4083. QueryValue(
  4084. IN HKEY hkey,
  4085. IN LPCWSTR lpwsValue,
  4086. IN OUT LPBYTE* lplpValue,
  4087. OUT LPDWORD lpdwSize
  4088. )
  4089. {
  4090. DWORD dwErr, dwType;
  4091. *lplpValue = NULL;
  4092. *lpdwSize = 0;
  4093. //
  4094. // retrieve the size of the value; if this fails,
  4095. // assume the value doesn't exist and return successfully
  4096. //
  4097. dwErr = RegQueryValueEx(
  4098. hkey, lpwsValue, NULL, &dwType, NULL, lpdwSize
  4099. );
  4100. if (dwErr != NO_ERROR) { return NO_ERROR; }
  4101. //
  4102. // allocate space for the value
  4103. //
  4104. *lplpValue = (LPBYTE)Malloc(*lpdwSize);
  4105. if (!lplpValue) { return ERROR_NOT_ENOUGH_MEMORY; }
  4106. //
  4107. // retrieve the data for the value
  4108. //
  4109. dwErr = RegQueryValueEx(
  4110. hkey, lpwsValue, NULL, &dwType, *lplpValue, lpdwSize
  4111. );
  4112. return dwErr;
  4113. }
  4114. //----------------------------------------------------------------------------
  4115. // Function: RegDeleteTree
  4116. //
  4117. // Removes an entire subtree from the registry.
  4118. //----------------------------------------------------------------------------
  4119. DWORD
  4120. RegDeleteTree(
  4121. IN HKEY hkey,
  4122. IN LPWSTR lpwsSubkey
  4123. )
  4124. {
  4125. HKEY hkdel;
  4126. DWORD dwErr;
  4127. PTSTR pszKey = NULL;
  4128. //
  4129. // open the key to be deleted
  4130. //
  4131. dwErr = RegOpenKeyEx(hkey, lpwsSubkey, 0, KEY_READ | KEY_WRITE | DELETE, &hkdel);
  4132. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  4133. do {
  4134. //
  4135. // retrieve information about the subkeys of the key
  4136. //
  4137. DWORD i, dwSize;
  4138. DWORD dwKeyCount, dwMaxKeyLength;
  4139. dwErr = RegQueryInfoKey(
  4140. hkdel, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLength,
  4141. NULL, NULL, NULL, NULL, NULL, NULL
  4142. );
  4143. if (dwErr != ERROR_SUCCESS) { break; }
  4144. //
  4145. // Allocate enough space for the longest keyname
  4146. //
  4147. pszKey = Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  4148. if (!pszKey) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  4149. //
  4150. // Enumerate the subkeys
  4151. //
  4152. for (i = 0; i < dwKeyCount; i++) {
  4153. //
  4154. // Get the name of the 0'th subkey
  4155. //
  4156. dwSize = dwMaxKeyLength + 1;
  4157. dwErr = RegEnumKeyEx(
  4158. hkdel, 0, pszKey, &dwSize, NULL, NULL, NULL, NULL
  4159. );
  4160. if (dwErr != ERROR_SUCCESS) { continue; }
  4161. //
  4162. // Make recursive call to delete the subkey
  4163. //
  4164. dwErr = RegDeleteTree(hkdel, pszKey);
  4165. }
  4166. } while(FALSE);
  4167. if (pszKey) { Free(pszKey); }
  4168. RegCloseKey(hkdel);
  4169. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  4170. //
  4171. // At this point all subkeys should have been deleted,
  4172. // and we can call the registry API to delete the argument key
  4173. //
  4174. return RegDeleteKey(hkey, lpwsSubkey);
  4175. }
  4176. //----------------------------------------------------------------------------
  4177. // Function: RestoreAndTranslateInterfaceKey
  4178. //
  4179. // Restores the interfaces key from the given file and then maps lan interface
  4180. // names from friendly versions to their guid equivalents.
  4181. //
  4182. //----------------------------------------------------------------------------
  4183. DWORD
  4184. RestoreAndTranslateInterfaceKey(
  4185. IN SERVERCB* pserver,
  4186. IN CHAR* pszFileName,
  4187. IN DWORD dwFlags
  4188. )
  4189. {
  4190. DWORD dwErr;
  4191. //
  4192. // Restore the interfaces key from the given file
  4193. //
  4194. dwErr = RegRestoreKeyA(pserver->hkeyInterfaces, pszFileName, dwFlags);
  4195. if (dwErr != NO_ERROR) { return dwErr; }
  4196. //
  4197. // Update the lan interface names
  4198. //
  4199. dwErr =
  4200. EnumLanInterfaces(
  4201. pserver,
  4202. pserver->hkeyInterfaces,
  4203. MapInterfaceNamesCb,
  4204. FALSE
  4205. );
  4206. return dwErr;
  4207. }
  4208. //----------------------------------------------------------------------------
  4209. // Function: ServerCbAdd
  4210. //
  4211. // Adds a SERVERCB to the global table.
  4212. //
  4213. // Assumes lock on MprConfig api's is held
  4214. //----------------------------------------------------------------------------
  4215. DWORD
  4216. ServerCbAdd(
  4217. IN SERVERCB* pServer)
  4218. {
  4219. DWORD dwErr = NO_ERROR;
  4220. // Create the global table if needed
  4221. //
  4222. if (g_htabServers == NULL)
  4223. {
  4224. dwErr = HashTabCreate(
  4225. SERVERCB_HASH_SIZE,
  4226. ServerCbHash,
  4227. ServerCbCompare,
  4228. NULL,
  4229. NULL,
  4230. NULL,
  4231. &g_htabServers);
  4232. if (dwErr != NO_ERROR)
  4233. {
  4234. return dwErr;
  4235. }
  4236. }
  4237. // Add the SERVERCB
  4238. //
  4239. return HashTabInsert(
  4240. g_htabServers,
  4241. (HANDLE)pServer->lpwsServerName,
  4242. (HANDLE)pServer);
  4243. }
  4244. //----------------------------------------------------------------------------
  4245. // Function: ServerCbHash
  4246. //
  4247. // Compares a server name to a SERVERCB
  4248. //----------------------------------------------------------------------------
  4249. int
  4250. ServerCbCompare(
  4251. IN HANDLE hKey,
  4252. IN HANDLE hData)
  4253. {
  4254. PWCHAR pszServer = (PWCHAR)hKey;
  4255. SERVERCB* pServer = (SERVERCB*)hData;
  4256. if (pszServer == NULL)
  4257. {
  4258. if (pServer->lpwsServerName == NULL)
  4259. {
  4260. return 0;
  4261. }
  4262. else
  4263. {
  4264. return -1;
  4265. }
  4266. }
  4267. else if (pServer->lpwsServerName == NULL)
  4268. {
  4269. return 1;
  4270. }
  4271. return lstrcmpi(pszServer, pServer->lpwsServerName);
  4272. }
  4273. DWORD
  4274. ServerCbDelete(
  4275. IN SERVERCB* pServer)
  4276. {
  4277. DWORD dwErr, dwCount = 0;
  4278. // Create the global table if needed
  4279. //
  4280. if (g_htabServers == NULL)
  4281. {
  4282. return ERROR_CAN_NOT_COMPLETE;
  4283. }
  4284. // Remove the SERVERCB
  4285. //
  4286. dwErr = HashTabRemove(
  4287. g_htabServers,
  4288. (HANDLE)pServer->lpwsServerName);
  4289. if (dwErr != NO_ERROR)
  4290. {
  4291. return dwErr;
  4292. }
  4293. // Cleanup the hash table if needed
  4294. //
  4295. dwErr = HashTabGetCount(g_htabServers, &dwCount);
  4296. if (dwErr != NO_ERROR)
  4297. {
  4298. return dwErr;
  4299. }
  4300. if (dwCount == 0)
  4301. {
  4302. HashTabCleanup(g_htabServers);
  4303. g_htabServers = NULL;
  4304. }
  4305. return NO_ERROR;
  4306. }
  4307. //----------------------------------------------------------------------------
  4308. // Function: ServerCbFind
  4309. //
  4310. // Searches the global table of server control blocks for a SERVERCB that
  4311. // corrosponds to the given server.
  4312. //
  4313. // Return values:
  4314. // NO_ERROR: a matching SERVERCB was found
  4315. // ERROR_NOT_FOUND: a matching SERVERCB was not found
  4316. // Standard error: an error occurred
  4317. //
  4318. // Notes:
  4319. // Assumes lock on the mpr config api's is held
  4320. //
  4321. //----------------------------------------------------------------------------
  4322. DWORD
  4323. ServerCbFind(
  4324. IN PWCHAR pszServer,
  4325. OUT SERVERCB** ppServerCB)
  4326. {
  4327. // Create the global table if needed
  4328. //
  4329. if (g_htabServers == NULL)
  4330. {
  4331. return ERROR_NOT_FOUND;
  4332. }
  4333. return HashTabFind(g_htabServers, (HANDLE)pszServer, (HANDLE*)ppServerCB);
  4334. }
  4335. //----------------------------------------------------------------------------
  4336. // Function: ServerCbHash
  4337. //
  4338. // Hash function used to define the index of a bucket
  4339. // containing a SERVERCB based on a server name
  4340. //----------------------------------------------------------------------------
  4341. ULONG
  4342. ServerCbHash(
  4343. IN HANDLE hData)
  4344. {
  4345. PWCHAR pszServer = (PWCHAR)hData;
  4346. DWORD dwTotal = 0;
  4347. while (pszServer && *pszServer)
  4348. {
  4349. dwTotal += (DWORD)(*pszServer);
  4350. pszServer++;
  4351. }
  4352. return dwTotal % SERVERCB_HASH_SIZE;
  4353. }
  4354. //----------------------------------------------------------------------------
  4355. // Function: StrDupW
  4356. //
  4357. // Returns a heap-allocated copy of the specified string.
  4358. //----------------------------------------------------------------------------
  4359. LPWSTR
  4360. StrDupW(
  4361. IN LPCWSTR lpws
  4362. )
  4363. {
  4364. INT len;
  4365. LPWSTR lpwsCopy;
  4366. if (!lpws) { return NULL; }
  4367. len = lstrlen(lpws) + 1;
  4368. lpwsCopy = (LPWSTR)Malloc(len * sizeof(WCHAR));
  4369. if (lpwsCopy) { lstrcpy(lpwsCopy, lpws); }
  4370. return lpwsCopy;
  4371. }
  4372. //----------------------------------------------------------------------------
  4373. // Function: TimeStampChanged
  4374. //
  4375. // Checks the current last-write-time for the given key,
  4376. // and returns TRUE if it is different from the given file-time.
  4377. // The new last-write-time is saved in 'pfiletime'.
  4378. //----------------------------------------------------------------------------
  4379. BOOL
  4380. TimeStampChanged(
  4381. IN HKEY hkey,
  4382. IN OUT FILETIME* pfiletime
  4383. )
  4384. {
  4385. DWORD dwErr;
  4386. FILETIME filetime;
  4387. //
  4388. // Read the new last-write-time
  4389. //
  4390. dwErr = RegQueryInfoKey(
  4391. hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  4392. NULL, NULL, &filetime
  4393. );
  4394. if (dwErr != NO_ERROR) { return FALSE; }
  4395. //
  4396. // Perform the comparison of the times
  4397. //
  4398. return (CompareFileTime(&filetime, pfiletime) ? TRUE : FALSE);
  4399. }
  4400. //----------------------------------------------------------------------------
  4401. // Function: TranslateAndSaveInterfaceKey
  4402. //
  4403. // Saves the interfaces key in the router's registry into the given file. All
  4404. // lan interfaces are stored with friendly interface names.
  4405. //
  4406. //----------------------------------------------------------------------------
  4407. DWORD
  4408. TranslateAndSaveInterfaceKey(
  4409. IN SERVERCB* pserver,
  4410. IN PWCHAR pwsFileName,
  4411. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  4412. )
  4413. {
  4414. static const WCHAR pszTemp[] = L"BackupInterfaces";
  4415. DWORD dwErr = NO_ERROR, dwDisposition;
  4416. HKEY hkTemp = NULL;
  4417. //
  4418. // Enable restore privelege
  4419. //
  4420. EnableBackupPrivilege(TRUE, SE_RESTORE_NAME);
  4421. //
  4422. // Create a temporary key into which the saved router configuration
  4423. // can be loaded.
  4424. //
  4425. dwErr =
  4426. RegCreateKeyExW(
  4427. pserver->hkeyParameters,
  4428. pszTemp,
  4429. 0,
  4430. NULL,
  4431. REG_OPTION_NON_VOLATILE,
  4432. KEY_READ | KEY_WRITE | DELETE,
  4433. NULL,
  4434. &hkTemp,
  4435. &dwDisposition
  4436. );
  4437. if (dwErr != NO_ERROR)
  4438. {
  4439. return dwErr;
  4440. }
  4441. do
  4442. {
  4443. //
  4444. // We only let one person at a time backup. The disposition lets
  4445. // us enforce this.
  4446. //
  4447. if (dwDisposition == REG_OPENED_EXISTING_KEY) {
  4448. dwErr = ERROR_CAN_NOT_COMPLETE;
  4449. break;
  4450. }
  4451. //
  4452. // Save the interfaces key into the given file.
  4453. //
  4454. DeleteFile(pwsFileName);
  4455. dwErr =
  4456. RegSaveKey(
  4457. pserver->hkeyInterfaces, pwsFileName, lpSecurityAttributes
  4458. );
  4459. if (dwErr != NO_ERROR) { break; }
  4460. //
  4461. // Restore the interfaces key into the temporary location
  4462. //
  4463. if ((dwErr = RegRestoreKey (hkTemp, pwsFileName, REG_FORCE_RESTORE)) != NO_ERROR) {
  4464. break;
  4465. }
  4466. DeleteFile(pwsFileName);
  4467. //
  4468. // Update the lan interface names
  4469. //
  4470. dwErr = EnumLanInterfaces(pserver, hkTemp, MapInterfaceNamesCb, TRUE);
  4471. if (dwErr != NO_ERROR) { break; }
  4472. //
  4473. // Save the updated info into the given file
  4474. //
  4475. dwErr = RegSaveKey(hkTemp, pwsFileName, lpSecurityAttributes);
  4476. if (dwErr != NO_ERROR) { break; }
  4477. } while (FALSE);
  4478. // Cleanup
  4479. {
  4480. //
  4481. // Delete, close, and remove the temporary key
  4482. //
  4483. if (hkTemp) {
  4484. DeleteRegistryTree(hkTemp);
  4485. RegCloseKey(hkTemp);
  4486. RegDeleteKey(pserver->hkeyParameters, pszTemp);
  4487. }
  4488. //
  4489. // Disable restore privelege
  4490. //
  4491. EnableBackupPrivilege(FALSE, SE_RESTORE_NAME);
  4492. }
  4493. return dwErr;
  4494. }
  4495. //----------------------------------------------------------------------------
  4496. // Function: UpdateTimeStamp
  4497. //
  4498. // Creates (or updates) a value named 'Stamp' under the given key,
  4499. // and saves the last-write-time for the key in 'pfiletime'.
  4500. //----------------------------------------------------------------------------
  4501. DWORD
  4502. UpdateTimeStamp(
  4503. IN HKEY hkey,
  4504. OUT FILETIME* pfiletime
  4505. )
  4506. {
  4507. DWORD dwErr, dwValue = 0;
  4508. //
  4509. // Set the 'Stamp' value under the 'hkey'
  4510. //
  4511. dwErr = RegSetValueEx(
  4512. hkey, c_szStamp, 0, REG_DWORD, (BYTE*)&dwValue, sizeof(dwValue)
  4513. );
  4514. if (dwErr != NO_ERROR) { return dwErr; }
  4515. //
  4516. // Read the new last-write-time
  4517. //
  4518. dwErr = RegQueryInfoKey(
  4519. hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  4520. NULL, pfiletime
  4521. );
  4522. return dwErr;
  4523. }