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.

679 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: I S D N R E G . C P P
  7. //
  8. // Contents: ISDN Wizard/PropertySheet registry functions
  9. //
  10. // Notes:
  11. //
  12. // Author: VBaliga 14 Jun 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <ncxbase.h>
  18. #include "isdncfg.h"
  19. #include "ncreg.h"
  20. #define NUM_D_CHANNELS_ALLOWED 16
  21. #define NUM_B_CHANNELS_ALLOWED 50
  22. // Reg key value names
  23. // For each ISDN card instance
  24. static const WCHAR c_szWanEndpoints[] = L"WanEndpoints";
  25. static const WCHAR c_szIsdnNumDChannels[] = L"IsdnNumDChannels";
  26. static const WCHAR c_szIsdnSwitchTypes[] = L"IsdnSwitchTypes";
  27. // For each D-channel
  28. static const WCHAR c_szIsdnSwitchType[] = L"IsdnSwitchType";
  29. static const WCHAR c_szIsdnNumBChannels[] = L"IsdnNumBChannels";
  30. // For each B-channel
  31. static const WCHAR c_szIsdnSpid[] = L"IsdnSpid";
  32. static const WCHAR c_szIsdnPhoneNumber[] = L"IsdnPhoneNumber";
  33. static const WCHAR c_szIsdnSubaddress[] = L"IsdnSubaddress";
  34. static const WCHAR c_szIsdnMultiNumbers[] = L"IsdnMultiSubscriberNumbers";
  35. /*
  36. Function:
  37. HrReadNthDChannelInfo
  38. Returns:
  39. HRESULT
  40. Description:
  41. Read the information for the dwIndex'th D-channel into pDChannel. If this
  42. function succeeds, it allocates pDChannel->pBChannel, which has to be freed
  43. by calling LocalFree().
  44. If there is an error in reading IsdnSwitchType, this function returns
  45. S_FALSE.
  46. If there is an error in opening the a B-channel key, or there is an error
  47. in reading IsdnSpid or IsdnPhoneNumber, this function returns S_FALSE, but
  48. with empty strings in pBChannel->szSpid and pBChannel->szPhoneNumber for
  49. that B-channel.
  50. */
  51. HRESULT
  52. HrReadNthDChannelInfo(
  53. HKEY hKeyIsdnBase,
  54. DWORD dwDChannelIndex,
  55. PISDN_D_CHANNEL pDChannel
  56. )
  57. {
  58. WCHAR szKeyName[20]; // _itow() uses only 17 wchars
  59. HKEY hKeyDChannel = NULL;
  60. HKEY hKeyBChannel = NULL;
  61. DWORD dwBChannelIndex;
  62. PISDN_B_CHANNEL pBChannel;
  63. HRESULT hr = E_FAIL;
  64. BOOL fReturnSFalse = FALSE;
  65. DWORD cbData;
  66. Assert(NULL == pDChannel->pBChannel);
  67. _itow(dwDChannelIndex, szKeyName, 10 /* radix */);
  68. hr = HrRegOpenKeyEx(hKeyIsdnBase, szKeyName, KEY_READ, &hKeyDChannel);
  69. if (FAILED(hr))
  70. {
  71. TraceTag(ttidISDNCfg, "Error opening D-channel %d. hr: %d",
  72. dwDChannelIndex, hr);
  73. goto LDone;
  74. }
  75. hr = HrRegQueryMultiSzWithAlloc(hKeyDChannel, c_szIsdnMultiNumbers,
  76. &pDChannel->mszMsnNumbers);
  77. if (FAILED(hr))
  78. {
  79. TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d. hr: %d",
  80. c_szIsdnMultiNumbers, dwDChannelIndex, hr);
  81. // Initialize to empty string
  82. //
  83. pDChannel->mszMsnNumbers = new WCHAR[1];
  84. if (pDChannel->mszMsnNumbers == NULL)
  85. {
  86. return(ERROR_NOT_ENOUGH_MEMORY);
  87. }
  88. *pDChannel->mszMsnNumbers = 0;
  89. // May not be present
  90. hr = S_OK;
  91. }
  92. hr = HrRegQueryDword(hKeyDChannel, c_szIsdnNumBChannels,
  93. &(pDChannel->dwNumBChannels));
  94. if (FAILED(hr))
  95. {
  96. TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d. hr: %d",
  97. c_szIsdnNumBChannels, dwDChannelIndex, hr);
  98. goto LDone;
  99. }
  100. if (NUM_B_CHANNELS_ALLOWED < pDChannel->dwNumBChannels ||
  101. 0 == pDChannel->dwNumBChannels)
  102. {
  103. // Actually, dwNumBChannels <= 23. We are protecting ourselves from
  104. // a corrupt registry.
  105. TraceTag(ttidISDNCfg, "%S in D-channel %d has invalid value: %d",
  106. c_szIsdnNumBChannels, dwDChannelIndex, pDChannel->dwNumBChannels);
  107. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  108. goto LDone;
  109. }
  110. pDChannel->pBChannel = (PISDN_B_CHANNEL)
  111. LocalAlloc(LPTR, sizeof(ISDN_B_CHANNEL) * pDChannel->dwNumBChannels);
  112. if (NULL == pDChannel->pBChannel)
  113. {
  114. hr = HrFromLastWin32Error();
  115. TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr);
  116. goto LDone;
  117. }
  118. ZeroMemory(pDChannel->pBChannel, sizeof(ISDN_B_CHANNEL) *
  119. pDChannel->dwNumBChannels);
  120. for (dwBChannelIndex = 0;
  121. dwBChannelIndex < pDChannel->dwNumBChannels;
  122. dwBChannelIndex++)
  123. {
  124. pBChannel = pDChannel->pBChannel + dwBChannelIndex;
  125. _itow(dwBChannelIndex, szKeyName, 10 /* radix */);
  126. hr = HrRegOpenKeyEx(hKeyDChannel, szKeyName, KEY_READ, &hKeyBChannel);
  127. if (FAILED(hr))
  128. {
  129. TraceTag(ttidISDNCfg, "Error opening B-channel %d in D-channel "
  130. "%d. hr: %d", dwBChannelIndex, dwDChannelIndex, hr);
  131. goto LForEnd;
  132. }
  133. cbData = sizeof(pBChannel->szSpid);
  134. hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnSpid, pBChannel->szSpid,
  135. &cbData);
  136. if (FAILED(hr))
  137. {
  138. TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, "
  139. "B-channel %d. hr: %d", c_szIsdnSpid,
  140. dwDChannelIndex, dwBChannelIndex, hr);
  141. // May not be present
  142. hr = S_OK;
  143. }
  144. cbData = sizeof(pBChannel->szPhoneNumber);
  145. hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnPhoneNumber,
  146. pBChannel->szPhoneNumber, &cbData);
  147. if (FAILED(hr))
  148. {
  149. TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, "
  150. "B-channel %d. hr: %d", c_szIsdnPhoneNumber,
  151. dwDChannelIndex, dwBChannelIndex, hr);
  152. // May not be present
  153. hr = S_OK;
  154. }
  155. cbData = sizeof(pBChannel->szSubaddress);
  156. hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnSubaddress,
  157. pBChannel->szSubaddress, &cbData);
  158. if (FAILED(hr))
  159. {
  160. TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, "
  161. "B-channel %d. hr: %d", c_szIsdnSubaddress,
  162. dwDChannelIndex, dwBChannelIndex, hr);
  163. // May not be present
  164. hr = S_OK;
  165. }
  166. LForEnd:
  167. if (FAILED(hr))
  168. {
  169. fReturnSFalse = TRUE;
  170. hr = S_OK;
  171. pBChannel->szSpid[0] = L'\0';
  172. pBChannel->szPhoneNumber[0] = L'\0';
  173. }
  174. RegSafeCloseKey(hKeyBChannel);
  175. }
  176. LDone:
  177. RegSafeCloseKey(hKeyDChannel);
  178. if (FAILED(hr))
  179. {
  180. LocalFree(pDChannel->pBChannel);
  181. pDChannel->pBChannel = NULL;
  182. }
  183. if (SUCCEEDED(hr) && fReturnSFalse)
  184. {
  185. TraceTag(ttidISDNCfg, "HrReadNthDChannelInfo(%d) returning S_FALSE",
  186. dwDChannelIndex);
  187. hr = S_FALSE;
  188. }
  189. TraceError("HrReadNthDChannelInfo", (S_FALSE == hr) ? S_OK: hr);
  190. return(hr);
  191. }
  192. /*
  193. Function:
  194. HrReadDChannelsInfo
  195. Returns:
  196. HRESULT
  197. Description:
  198. Read the D-channel information into *ppDChannel. If the function fails,
  199. *ppDChannel will be NULL.
  200. */
  201. HRESULT
  202. HrReadDChannelsInfo(
  203. HKEY hKeyISDNBase,
  204. DWORD dwNumDChannels,
  205. PISDN_D_CHANNEL* ppDChannel
  206. )
  207. {
  208. HRESULT hr = E_FAIL;
  209. BOOL fReturnSFalse = FALSE;
  210. PISDN_D_CHANNEL pDChannel;
  211. DWORD dwIndex;
  212. pDChannel = (PISDN_D_CHANNEL)
  213. LocalAlloc(LPTR, sizeof(ISDN_D_CHANNEL) * dwNumDChannels);
  214. if (NULL == pDChannel)
  215. {
  216. hr = HrFromLastWin32Error();
  217. TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr);
  218. goto LDone;
  219. }
  220. // If there is an error, we will free these variables if they are not NULL.
  221. for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++)
  222. {
  223. Assert(NULL == pDChannel[dwIndex].pBChannel);
  224. }
  225. for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++)
  226. {
  227. hr = HrReadNthDChannelInfo(hKeyISDNBase, dwIndex, pDChannel + dwIndex);
  228. if (FAILED(hr))
  229. {
  230. goto LDone;
  231. }
  232. if (S_FALSE == hr)
  233. {
  234. fReturnSFalse = TRUE;
  235. }
  236. }
  237. LDone:
  238. if (FAILED(hr))
  239. {
  240. if (NULL != pDChannel)
  241. {
  242. for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++)
  243. {
  244. LocalFree(pDChannel[dwIndex].pBChannel);
  245. }
  246. LocalFree(pDChannel);
  247. *ppDChannel = NULL;
  248. }
  249. }
  250. else
  251. {
  252. *ppDChannel = pDChannel;
  253. }
  254. if (SUCCEEDED(hr) && fReturnSFalse)
  255. {
  256. TraceTag(ttidISDNCfg, "HrReadDChannelsInfo() returning S_FALSE");
  257. hr = S_FALSE;
  258. }
  259. TraceError("HrReadDChannelsInfo", (S_FALSE == hr) ? S_OK : hr);
  260. return(hr);
  261. }
  262. /*
  263. Function:
  264. HrReadISDNPropertiesInfo
  265. Returns:
  266. HRESULT
  267. Description:
  268. Read the ISDN registry structure into the config info. If the function
  269. fails, *ppISDNConfig will be NULL. Else, *ppISDNConfig has to be freed
  270. by calling FreeISDNPropertiesInfo().
  271. */
  272. HRESULT
  273. HrReadIsdnPropertiesInfo(
  274. HKEY hKeyIsdnBase,
  275. HDEVINFO hdi,
  276. PSP_DEVINFO_DATA pdeid,
  277. PISDN_CONFIG_INFO* ppIsdnConfig
  278. )
  279. {
  280. HRESULT hr = E_FAIL;
  281. PISDN_CONFIG_INFO pIsdnConfig;
  282. DWORD dwIndex;
  283. pIsdnConfig = (PISDN_CONFIG_INFO)
  284. LocalAlloc(LPTR, sizeof(ISDN_CONFIG_INFO));
  285. if (NULL == pIsdnConfig)
  286. {
  287. hr = HrFromLastWin32Error();
  288. TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr);
  289. goto LDone;
  290. }
  291. ZeroMemory(pIsdnConfig, sizeof(ISDN_CONFIG_INFO));
  292. pIsdnConfig->hdi = hdi;
  293. pIsdnConfig->pdeid = pdeid;
  294. // If there is an error, we will free these variables if they are not NULL.
  295. Assert(NULL == pIsdnConfig->pDChannel);
  296. hr = HrRegQueryDword(hKeyIsdnBase, c_szWanEndpoints,
  297. &(pIsdnConfig->dwWanEndpoints));
  298. if (FAILED(hr))
  299. {
  300. TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szWanEndpoints,
  301. hr);
  302. goto LDone;
  303. }
  304. hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnNumDChannels,
  305. &(pIsdnConfig->dwNumDChannels));
  306. if (FAILED(hr))
  307. {
  308. TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szIsdnNumDChannels,
  309. hr);
  310. goto LDone;
  311. }
  312. if (NUM_D_CHANNELS_ALLOWED < pIsdnConfig->dwNumDChannels ||
  313. 0 == pIsdnConfig->dwNumDChannels)
  314. {
  315. // Actually, dwNumDChannels <= 8. We are protecting ourselves from
  316. // a corrupt registry.
  317. TraceTag(ttidISDNCfg, "%S has invalid value: %d", c_szIsdnNumDChannels,
  318. pIsdnConfig->dwNumDChannels);
  319. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  320. // Setting dwNumDChannels to 0 will help us when we try to free the
  321. // allocated ISDN_B_CHANNEL's
  322. pIsdnConfig->dwNumDChannels = 0;
  323. goto LDone;
  324. }
  325. hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnSwitchTypes,
  326. &pIsdnConfig->dwSwitchTypes);
  327. if (FAILED(hr))
  328. {
  329. TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szIsdnSwitchTypes,
  330. hr);
  331. goto LDone;
  332. }
  333. hr = HrReadDChannelsInfo(hKeyIsdnBase, pIsdnConfig->dwNumDChannels,
  334. &(pIsdnConfig->pDChannel));
  335. if (FAILED(hr))
  336. {
  337. goto LDone;
  338. }
  339. // A PRI adapter is one that has more than 2 B channels per D channel.
  340. // Since all D channels should have the same number of B channels, the
  341. // safest thing to do is pick the first D channel
  342. //
  343. pIsdnConfig->fIsPri = (pIsdnConfig->pDChannel[0].dwNumBChannels > 2);
  344. #if DBG
  345. if (pIsdnConfig->fIsPri)
  346. {
  347. TraceTag(ttidISDNCfg, "This is a PRI adapter!");
  348. }
  349. #endif
  350. hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnSwitchType,
  351. &(pIsdnConfig->dwCurSwitchType));
  352. if (FAILED(hr))
  353. {
  354. Assert(ISDN_SWITCH_NONE == pIsdnConfig->dwCurSwitchType);
  355. TraceTag(ttidISDNCfg, "Error reading %S. If this is a new install, "
  356. "then this is expected. hr: %d", c_szIsdnSwitchType,
  357. hr);
  358. // Switch type won't exist on a new install of the card so this is ok
  359. hr = S_OK;
  360. }
  361. LDone:
  362. if (FAILED(hr))
  363. {
  364. if (NULL != pIsdnConfig)
  365. {
  366. if (NULL != pIsdnConfig->pDChannel)
  367. {
  368. for (dwIndex = 0;
  369. dwIndex < pIsdnConfig->dwNumDChannels;
  370. dwIndex++)
  371. {
  372. LocalFree(pIsdnConfig->pDChannel[dwIndex].pBChannel);
  373. }
  374. LocalFree(pIsdnConfig->pDChannel);
  375. }
  376. LocalFree(pIsdnConfig);
  377. *ppIsdnConfig = NULL;
  378. }
  379. }
  380. else
  381. {
  382. *ppIsdnConfig = pIsdnConfig;
  383. }
  384. TraceError("HrReadIsdnPropertiesInfo", hr);
  385. return(hr);
  386. }
  387. /*
  388. Function:
  389. HrWriteIsdnPropertiesInfo
  390. Returns:
  391. HRESULT
  392. Description:
  393. Write the ISDN config info back into the registry.
  394. */
  395. HRESULT
  396. HrWriteIsdnPropertiesInfo(
  397. HKEY hKeyIsdnBase,
  398. PISDN_CONFIG_INFO pIsdnConfig
  399. )
  400. {
  401. WCHAR szKeyName[20]; // _itow() uses only 17 wchars
  402. HRESULT hr = E_FAIL;
  403. HKEY hKeyDChannel = NULL;
  404. HKEY hKeyBChannel = NULL;
  405. DWORD dwDChannelIndex;
  406. DWORD dwBChannelIndex;
  407. PISDN_D_CHANNEL pDChannel;
  408. PISDN_B_CHANNEL pBChannel;
  409. Assert(NUM_D_CHANNELS_ALLOWED >= pIsdnConfig->dwNumDChannels);
  410. hr = HrRegSetDword(hKeyIsdnBase, c_szIsdnSwitchType,
  411. pIsdnConfig->dwCurSwitchType);
  412. if (FAILED(hr))
  413. {
  414. TraceTag(ttidISDNCfg, "Error writing %S. hr: %d",
  415. c_szIsdnSwitchType, hr);
  416. goto LOuterForEnd;
  417. }
  418. for (dwDChannelIndex = 0;
  419. dwDChannelIndex < pIsdnConfig->dwNumDChannels;
  420. dwDChannelIndex++)
  421. {
  422. pDChannel = pIsdnConfig->pDChannel + dwDChannelIndex;
  423. _itow(dwDChannelIndex, szKeyName, 10 /* radix */);
  424. hr = HrRegOpenKeyEx(hKeyIsdnBase, szKeyName, KEY_WRITE,
  425. &hKeyDChannel);
  426. if (FAILED(hr))
  427. {
  428. TraceTag(ttidISDNCfg, "Error opening D-channel %d. hr: %d",
  429. dwDChannelIndex, hr);
  430. goto LOuterForEnd;
  431. }
  432. hr = HrRegSetMultiSz(hKeyDChannel, c_szIsdnMultiNumbers,
  433. pDChannel->mszMsnNumbers);
  434. if (FAILED(hr))
  435. {
  436. TraceTag(ttidISDNCfg, "Error writing %S. hr: %d",
  437. c_szIsdnMultiNumbers, hr);
  438. goto LOuterForEnd;
  439. }
  440. Assert(NUM_B_CHANNELS_ALLOWED >= pDChannel->dwNumBChannels);
  441. for (dwBChannelIndex = 0;
  442. dwBChannelIndex < pDChannel->dwNumBChannels;
  443. dwBChannelIndex++)
  444. {
  445. pBChannel = pDChannel->pBChannel + dwBChannelIndex;
  446. _itow(dwBChannelIndex, szKeyName, 10 /* radix */);
  447. hr = HrRegCreateKeyEx(hKeyDChannel, szKeyName,
  448. REG_OPTION_NON_VOLATILE, KEY_WRITE,
  449. NULL, &hKeyBChannel, NULL);
  450. if (FAILED(hr))
  451. {
  452. TraceTag(ttidISDNCfg, "Error opening B-channel %d in "
  453. "D-channel %d. hr: %d", dwBChannelIndex,
  454. dwDChannelIndex, hr);
  455. goto LInnerForEnd;
  456. }
  457. hr = HrRegSetSz(hKeyBChannel, c_szIsdnSpid, pBChannel->szSpid);
  458. if (FAILED(hr))
  459. {
  460. TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, "
  461. "B-channel %d. hr: %d", c_szIsdnSpid,
  462. dwDChannelIndex, dwBChannelIndex, hr);
  463. goto LInnerForEnd;
  464. }
  465. hr = HrRegSetSz(hKeyBChannel, c_szIsdnPhoneNumber,
  466. pBChannel->szPhoneNumber);
  467. if (FAILED(hr))
  468. {
  469. TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, "
  470. "B-channel %d. hr: %d", c_szIsdnPhoneNumber,
  471. dwDChannelIndex, dwBChannelIndex, hr);
  472. goto LInnerForEnd;
  473. }
  474. hr = HrRegSetSz(hKeyBChannel, c_szIsdnSubaddress,
  475. pBChannel->szSubaddress);
  476. if (FAILED(hr))
  477. {
  478. TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, "
  479. "B-channel %d. hr: %d", c_szIsdnSubaddress,
  480. dwDChannelIndex, dwBChannelIndex, hr);
  481. goto LInnerForEnd;
  482. }
  483. LInnerForEnd:
  484. RegSafeCloseKey(hKeyBChannel);
  485. if (FAILED(hr))
  486. {
  487. goto LOuterForEnd;
  488. }
  489. }
  490. LOuterForEnd:
  491. RegSafeCloseKey(hKeyDChannel);
  492. if (FAILED(hr))
  493. {
  494. goto LDone;
  495. }
  496. }
  497. LDone:
  498. TraceError("HrWriteIsdnPropertiesInfo", hr);
  499. return(hr);
  500. }
  501. /*
  502. Function:
  503. FreeIsdnPropertiesInfo
  504. Returns:
  505. HRESULT
  506. Description:
  507. Free the structure allocated by HrReadIsdnPropertiesInfo.
  508. */
  509. VOID
  510. FreeIsdnPropertiesInfo(
  511. PISDN_CONFIG_INFO pIsdnConfig
  512. )
  513. {
  514. DWORD dwIndex;
  515. if (NULL == pIsdnConfig)
  516. {
  517. return;
  518. }
  519. if (NULL != pIsdnConfig->pDChannel)
  520. {
  521. for (dwIndex = 0; dwIndex < pIsdnConfig->dwNumDChannels; dwIndex++)
  522. {
  523. LocalFree(pIsdnConfig->pDChannel[dwIndex].pBChannel);
  524. delete [] pIsdnConfig->pDChannel[dwIndex].mszMsnNumbers;
  525. }
  526. LocalFree(pIsdnConfig->pDChannel);
  527. }
  528. LocalFree(pIsdnConfig);
  529. }