Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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