Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4680 lines
126 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxreg.c
  5. Abstract:
  6. This module wraps all of the registry access
  7. for the fax server.
  8. Author:
  9. Wesley Witt (wesw) 9-June-1996
  10. Revision History:
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <tchar.h>
  16. #include <objbase.h>
  17. #include <wincrypt.h>
  18. #include <Shlwapi.h.>
  19. #include "fxsapip.h"
  20. #include "faxutil.h"
  21. #include "faxext.h"
  22. #include "faxreg.h"
  23. #include "faxsvcrg.h"
  24. #define FAX_CATEGORY_COUNT 4
  25. #define BAD_FOLDER_STRING TEXT("\\\\\\")
  26. static BYTE const gsc_baEntropy [] = {0x46, 0x41, 0x58, 0x43, 0x4F, 0x56, 0x45, 0x52, 0x2D, 0x56, 0x45, 0x52,
  27. 0x30, 0x30, 0x35, 0x77, 0x87, 0x00, 0x00, 0x00};
  28. static
  29. BOOL
  30. SetRegistrySecureBinary (
  31. HKEY hKey,
  32. LPCTSTR lpctstrValueName,
  33. LPBYTE lpbValue,
  34. DWORD dwValueSize,
  35. BOOL bOptionallyNonSecure
  36. )
  37. /*++
  38. Routine name : SetRegistrySecureBinary
  39. Routine description:
  40. Stores a binary blob in the registry with encryption
  41. Author:
  42. Eran Yariv (EranY), Sep, 2001
  43. Arguments:
  44. hKey [in] - Handle to registry key (open)
  45. lpctstrValueName [in] - Name of value
  46. lpbValue [in] - Blob to store
  47. dwValueSize [in] - Size of data blob
  48. bOptionallyNonSecure [in] - Do we allow the registry entry to be non-secure?
  49. If FALSE, the data will always be written encrypted.
  50. If TRUE, the data will be written encrypted but prefixed with
  51. a string (FAX_REG_SECURITY_PREFIX).
  52. Return Value:
  53. TRUE if success, FALSE otherwise.
  54. Remarks:
  55. Data is stored in REG_BINARY format.
  56. Encryption has no UI
  57. Encryption is machine based (if you change the account under which the server is running, it will
  58. still be able to read and decrypt the encrypted data).
  59. --*/
  60. {
  61. BOOL bRes = FALSE;
  62. DEBUG_FUNCTION_NAME(TEXT("SetRegistrySecureBinary"));
  63. Assert (hKey && lpbValue && dwValueSize);
  64. //
  65. // Start by encrypting the value
  66. //
  67. DATA_BLOB DataIn;
  68. DATA_BLOB DataOut = {0};
  69. DataIn.pbData = lpbValue;
  70. DataIn.cbData = dwValueSize;
  71. DATA_BLOB DataEntropy;
  72. DataEntropy.pbData = (BYTE*)gsc_baEntropy;
  73. DataEntropy.cbData = sizeof (gsc_baEntropy);
  74. if (!CryptProtectData(
  75. &DataIn,
  76. TEXT("Description"), // No description sting.
  77. &DataEntropy, // We're using the cover page signature as an additional entropy
  78. NULL, // Reserved.
  79. NULL, // No user prompt
  80. CRYPTPROTECT_UI_FORBIDDEN, // Presenting a user interface (UI) is not an option.
  81. &DataOut))
  82. {
  83. DWORD dwRes = GetLastError ();
  84. DebugPrintEx(
  85. DEBUG_ERR,
  86. TEXT("CryptProtectData failed with %ld"),
  87. dwRes);
  88. return bRes;
  89. }
  90. if (bOptionallyNonSecure)
  91. {
  92. //
  93. // Need to prefix the data with FAX_REG_SECURITY_PREFIX.
  94. // This is done so that the matching reading function can handle secure and non-secure data
  95. // correctly.
  96. //
  97. DWORD dwPrefixSize = sizeof (TCHAR) * wcslen (FAX_REG_SECURITY_PREFIX);
  98. DWORD dwSize = dwPrefixSize + DataOut.cbData;
  99. BYTE *pPrefixedData = (BYTE*)LocalAlloc (LPTR, dwSize);
  100. if (!pPrefixedData)
  101. {
  102. DWORD dwRes = GetLastError ();
  103. DebugPrintEx(
  104. DEBUG_ERR,
  105. TEXT("LocalAlloc failed with %ld"),
  106. dwRes);
  107. goto exit;
  108. }
  109. memcpy (pPrefixedData, FAX_REG_SECURITY_PREFIX, dwPrefixSize);
  110. memcpy (&pPrefixedData[dwPrefixSize], DataOut.pbData, DataOut.cbData);
  111. LocalFree (DataOut.pbData);
  112. DataOut.pbData = pPrefixedData;
  113. DataOut.cbData = dwSize;
  114. }
  115. //
  116. // Store the data in the registry (as binary)
  117. //
  118. if (!SetRegistryBinary(
  119. hKey,
  120. lpctstrValueName,
  121. DataOut.pbData,
  122. DataOut.cbData))
  123. {
  124. DWORD dwRes = GetLastError ();
  125. DebugPrintEx(
  126. DEBUG_ERR,
  127. TEXT("SetRegistryBinary failed with %ld"),
  128. dwRes);
  129. goto exit;
  130. }
  131. bRes = TRUE;
  132. exit:
  133. LocalFree (DataOut.pbData);
  134. return bRes;
  135. } // SetRegistrySecureBinary
  136. BOOL
  137. SetRegistrySecureString (
  138. HKEY hKey,
  139. LPCTSTR lpctstrValueName,
  140. LPCTSTR lpctstrValue,
  141. BOOL bOptionallyNonSecure
  142. )
  143. /*++
  144. Routine name : SetRegistrySecureString
  145. Routine description:
  146. Stores a string in the registry with encryption
  147. Author:
  148. Eran Yariv (EranY), Jul, 2000
  149. Arguments:
  150. hKey [in] - Handle to registry key (open)
  151. lpctstrValueName [in] - Name of value
  152. lpctstrValue [in] - String to store
  153. bOptionallyNonSecure [in] - Do we allow the registry entry to be non-secure?
  154. If FALSE, the data will always be written encrypted.
  155. If TRUE, the data will be written encrypted but prefixed with
  156. a string (FAX_REG_SECURITY_PREFIX).
  157. Return Value:
  158. TRUE if success, FALSE otherwise.
  159. Remarks:
  160. String is stored in REG_BINARY format.
  161. Encryption has no UI
  162. Encryption is machine based (if you change the account under which the server is running, it will
  163. still be able to read and decrypt the encrypted data).
  164. --*/
  165. {
  166. DEBUG_FUNCTION_NAME(TEXT("SetRegistrySecureString"));
  167. return SetRegistrySecureBinary (hKey,
  168. lpctstrValueName,
  169. (LPBYTE)lpctstrValue,
  170. (lstrlen(lpctstrValue) + 1) * sizeof (TCHAR),
  171. bOptionallyNonSecure);
  172. } // SetRegistrySecureString
  173. static
  174. DWORD
  175. GetRegistrySecureBinary(
  176. HKEY hKey,
  177. LPCTSTR lpctstrValueName,
  178. LPBYTE *ppData,
  179. LPDWORD lpdwSize,
  180. BOOL bOptionallyNonSecure,
  181. FAX_ENUM_DATA_ENCRYPTION* pDataDecrypted
  182. )
  183. /*++
  184. Routine name : GetRegistrySecureBinary
  185. Routine description:
  186. Reads an decrypts a secure registry string
  187. Author:
  188. Eran Yariv (EranY), Jul, 2000
  189. Arguments:
  190. hKey [in] - Handle to registry key (open)
  191. lpctstrValueName [in] - Name of value
  192. ppData [out] - Allocated return buffer
  193. lpdwSize [out] - Allocated return buffer size (in bytes)
  194. bOptionallyNonSecure [in] - Do we allow the registry entry to be non-secure?
  195. If FALSE, the data will always be read and decrypted.
  196. If TRUE, the data will be read and checked for a prefix
  197. string (FAX_REG_SECURITY_PREFIX) before it is decrypted.
  198. If the prefix string is not there, the data will not be
  199. decrypted and will be returned as-is.
  200. pDataDecrypted [out] - Points to a FAX_ENUM_DATA_ENCRYPTION that on return is FAX_DATA_ENCRYPTED if the data was decrypted,
  201. and FAX_DATA_NOT_ENCRYPTED if the data was not decrypted and was returned as is.
  202. FAX_NO_DATA means that this information is not available.
  203. Ignored if NULL;
  204. Return Value:
  205. Win32 error code
  206. Remarks:
  207. String is stored in REG_BINARY format.
  208. String was stored by calling SetRegistrySecureBinary().
  209. Caller should MemFree return value.
  210. --*/
  211. {
  212. DATA_BLOB DataIn;
  213. DWORD dwRes = ERROR_SUCCESS;
  214. DATA_BLOB DataOut = {0};
  215. DATA_BLOB DataEntropy;
  216. DEBUG_FUNCTION_NAME(TEXT("GetRegistrySecureBinary"));
  217. Assert (hKey && ppData && lpdwSize);
  218. if (NULL != pDataDecrypted)
  219. {
  220. *pDataDecrypted = FAX_NO_DATA;
  221. }
  222. //
  223. // Get the registry data first
  224. //
  225. DataIn.pbData = GetRegistryBinary(
  226. hKey,
  227. lpctstrValueName,
  228. &DataIn.cbData);
  229. if (!DataIn.pbData)
  230. {
  231. //
  232. // Couldn't read data
  233. //
  234. dwRes = GetLastError ();
  235. DebugPrintEx(
  236. DEBUG_WRN,
  237. TEXT("GetRegistryBinary failed with %ld"),
  238. dwRes);
  239. return dwRes;
  240. }
  241. if (1 == DataIn.cbData)
  242. {
  243. //
  244. // Data wasn't found in the registry.
  245. // Current implementation of GetRegistryBinary returns a 1-byte buffer of 0 in that case.
  246. // We know for sure that data encrypted with CryptProtectData must be longer than 10 bytes.
  247. //
  248. MemFree (DataIn.pbData);
  249. DebugPrintEx(
  250. DEBUG_WRN,
  251. TEXT("GetRegistryBinary found no data for %s"),
  252. lpctstrValueName);
  253. return ERROR_FILE_NOT_FOUND;
  254. }
  255. //
  256. // We got the data - decrypt it
  257. //
  258. DataEntropy.pbData = (BYTE*)gsc_baEntropy;
  259. DataEntropy.cbData = sizeof (gsc_baEntropy);
  260. if (bOptionallyNonSecure)
  261. {
  262. //
  263. // Data is allowed to be non-secure
  264. //
  265. DWORD dwPrefixSize = sizeof (TCHAR) * wcslen (FAX_REG_SECURITY_PREFIX);
  266. if ((DataIn.cbData <= dwPrefixSize) ||
  267. memcmp (DataIn.pbData, FAX_REG_SECURITY_PREFIX, dwPrefixSize))
  268. {
  269. //
  270. // Data length is too short or data does not start with encryption signature.
  271. // The data we're reading is non-secure. Just return it as is.
  272. //
  273. *lpdwSize = DataIn.cbData;
  274. *ppData = DataIn.pbData;
  275. if (pDataDecrypted)
  276. {
  277. *pDataDecrypted = FAX_DATA_NOT_ENCRYPTED;
  278. }
  279. return ERROR_SUCCESS;
  280. }
  281. else
  282. {
  283. //
  284. // The data starts with encryption signature.
  285. // Actual encrypted data follows signature.
  286. //
  287. BYTE *pRealData;
  288. if (pDataDecrypted)
  289. {
  290. *pDataDecrypted = FAX_DATA_ENCRYPTED;
  291. }
  292. DataIn.cbData -= dwPrefixSize;
  293. pRealData = (LPBYTE)MemAlloc (DataIn.cbData);
  294. if (!pRealData)
  295. {
  296. dwRes = GetLastError ();
  297. DebugPrintEx(
  298. DEBUG_ERR,
  299. TEXT("MemAlloc failed with %ld"),
  300. dwRes);
  301. goto exit;
  302. }
  303. memcpy (pRealData, &(DataIn.pbData[dwPrefixSize]), DataIn.cbData);
  304. MemFree (DataIn.pbData);
  305. DataIn.pbData = pRealData;
  306. }
  307. }
  308. else
  309. {
  310. //
  311. // The data is always encrypted
  312. //
  313. if (pDataDecrypted)
  314. {
  315. *pDataDecrypted = FAX_DATA_ENCRYPTED;
  316. }
  317. }
  318. if (!CryptUnprotectData(
  319. &DataIn, // Data to decrypt
  320. NULL, // Not interested in description
  321. &DataEntropy, // Entropy in use
  322. NULL, // Reserved
  323. NULL, // No prompt
  324. CRYPTPROTECT_UI_FORBIDDEN, // Presenting a user interface (UI) is not an option.
  325. &DataOut)) // Out data
  326. {
  327. dwRes = GetLastError ();
  328. DebugPrintEx(
  329. DEBUG_ERR,
  330. TEXT("CryptUnprotectData failed with %ld"),
  331. dwRes);
  332. goto exit;
  333. }
  334. //
  335. // Use our own memory allocation
  336. //
  337. *lpdwSize = DataOut.cbData;
  338. *ppData = (LPBYTE)MemAlloc (DataOut.cbData);
  339. if (!(*ppData))
  340. {
  341. dwRes = GetLastError ();
  342. goto exit;
  343. }
  344. memcpy (*ppData, DataOut.pbData, DataOut.cbData);
  345. Assert (ERROR_SUCCESS == dwRes);
  346. exit:
  347. if (DataOut.pbData)
  348. {
  349. SecureZeroMemory(DataOut.pbData, DataOut.cbData);
  350. LocalFree (DataOut.pbData);
  351. }
  352. MemFree (DataIn.pbData);
  353. return dwRes;
  354. } // GetRegistrySecureBinary
  355. LPTSTR
  356. GetRegistrySecureString(
  357. HKEY hKey,
  358. LPCTSTR lpctstrValueName,
  359. LPCTSTR lpctstrDefaultValue,
  360. BOOL bOptionallyNonSecure,
  361. FAX_ENUM_DATA_ENCRYPTION* pDataDecrypted
  362. )
  363. /*++
  364. Routine name : GetRegistrySecureString
  365. Routine description:
  366. Reads an decrypts a secure registry string
  367. Author:
  368. Eran Yariv (EranY), Jul, 2000
  369. Arguments:
  370. hKey [in] - Handle to registry key (open)
  371. lpctstrValueName [in] - Name of value
  372. lpctstrDefaultValue [in] - Default value
  373. bOptionallyNonSecure [in] - Do we allow the registry entry to be non-secure?
  374. If FALSE, the data will always be read and decrypted.
  375. If TRUE, the data will be read and checked for a prefix
  376. string (FAX_REG_SECURITY_PREFIX) before it is decrypted.
  377. If the prefix string is not there, the data will not be
  378. decrypted and will be returned as-is.
  379. pDataDecrypted [out] - Points to a FAX_ENUM_DATA_ENCRYPTION that on return is FAX_DATA_ENCRYPTED if the data was decrypted,
  380. and FAX_DATA_NOT_ENCRYPTED if the data was not decrypted and was returned as is.
  381. FAX_NO_DATA means that this information is not available.
  382. Ignored if NULL;
  383. Return Value:
  384. String read or NULL on error
  385. Remarks:
  386. String is stored in REG_BINARY format.
  387. String was stored by calling SetRegistrySecureString().
  388. Caller should MemFree return value.
  389. --*/
  390. {
  391. LPTSTR lptstrResult = NULL;
  392. DWORD dwRes;
  393. DWORD dwSize;
  394. DEBUG_FUNCTION_NAME(TEXT("GetRegistrySecureString"));
  395. dwRes = GetRegistrySecureBinary (hKey,
  396. lpctstrValueName,
  397. (LPBYTE*)&lptstrResult,
  398. &dwSize,
  399. bOptionallyNonSecure,
  400. pDataDecrypted);
  401. if (ERROR_SUCCESS != dwRes)
  402. {
  403. //
  404. // Error reading or decrypting data - return default
  405. //
  406. return StringDup (lpctstrDefaultValue);
  407. }
  408. //
  409. // Assert the read binary blob is indeed a string by checing for EOSTR at the end.
  410. //
  411. Assert (lptstrResult[dwSize / sizeof (TCHAR) - 1] == TEXT('\0'));
  412. return lptstrResult;
  413. } // GetRegistrySecureString
  414. static
  415. DWORD
  416. OpenExtensionKey (
  417. DWORD dwDeviceId,
  418. FAX_ENUM_DEVICE_ID_SOURCE DevIdSrc,
  419. PHKEY lphKey
  420. );
  421. BOOL
  422. EnumDeviceProviders(
  423. HKEY hSubKey,
  424. LPWSTR SubKeyName,
  425. DWORD Index,
  426. LPVOID lpFaxReg
  427. )
  428. {
  429. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  430. DEBUG_FUNCTION_NAME(TEXT("EnumDeviceProviders"));
  431. if (SubKeyName == NULL) {
  432. //
  433. // The enumeration function has called us with the parent key.
  434. // Index should contain the number of subkeys. In this case this is the number of
  435. // providers subkeys.
  436. //
  437. if (Index) {
  438. FaxReg->DeviceProviders = (PREG_DEVICE_PROVIDER) MemAlloc( Index * sizeof(REG_DEVICE_PROVIDER) );
  439. if (!FaxReg->DeviceProviders) {
  440. return FALSE;
  441. }
  442. }
  443. return TRUE;
  444. }
  445. if (FaxReg == NULL || FaxReg->DeviceProviders == NULL) {
  446. return FALSE;
  447. }
  448. memset(&FaxReg->DeviceProviders[Index],0,sizeof(REG_DEVICE_PROVIDER));
  449. //
  450. // Check the APIVersion and see if this is an EFSP
  451. //
  452. FaxReg->DeviceProviders[Index].dwAPIVersion = GetRegistryDword(hSubKey, REGVAL_PROVIDER_API_VERSION);
  453. if (FSPI_API_VERSION_1 == FaxReg->DeviceProviders[Index].dwAPIVersion ||
  454. 0 == FaxReg->DeviceProviders[Index].dwAPIVersion)
  455. {
  456. LPTSTR lptstrGUID;
  457. //
  458. // This is a legacy FSP
  459. //
  460. FaxReg->DeviceProviders[Index].FriendlyName = GetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, EMPTY_STRING );
  461. FaxReg->DeviceProviders[Index].ImageName = GetRegistryStringExpand( hSubKey, REGVAL_IMAGE_NAME, EMPTY_STRING );
  462. FaxReg->DeviceProviders[Index].ProviderName = GetRegistryString( hSubKey, REGVAL_PROVIDER_NAME,EMPTY_STRING );
  463. FaxReg->DeviceProviders[Index].dwAPIVersion = FSPI_API_VERSION_1;
  464. lptstrGUID = GetRegistryString( hSubKey, REGVAL_PROVIDER_GUID,EMPTY_STRING );
  465. if ( (NULL == lptstrGUID) || (0 == _tcscmp(lptstrGUID , EMPTY_STRING)) )
  466. {
  467. //
  468. // This FSP was registerd using the legacy registration API
  469. // Use the provider unique name as a "GUID"
  470. //
  471. MemFree (lptstrGUID);
  472. lptstrGUID = StringDup(SubKeyName);
  473. }
  474. FaxReg->DeviceProviders[Index].lptstrGUID = lptstrGUID;
  475. }
  476. else
  477. {
  478. //
  479. // API_VERSION we do not support
  480. //
  481. DebugPrintEx(
  482. DEBUG_ERR,
  483. TEXT("Unknown API version : 0x%08X"),
  484. FaxReg->DeviceProviders[Index].dwAPIVersion);
  485. }
  486. return TRUE;
  487. }
  488. BOOL
  489. EnumDeviceProvidersChange(
  490. HKEY hSubKey,
  491. LPWSTR SubKeyName,
  492. DWORD Index,
  493. LPVOID lpFaxReg
  494. )
  495. {
  496. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  497. if (SubKeyName == NULL) {
  498. //
  499. // called once for the subkey
  500. //
  501. return TRUE;
  502. }
  503. if (FaxReg == NULL || FaxReg->DeviceProviders == NULL) {
  504. return FALSE;
  505. }
  506. SetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, FaxReg->DeviceProviders[Index].FriendlyName );
  507. SetRegistryStringExpand( hSubKey, REGVAL_IMAGE_NAME, FaxReg->DeviceProviders[Index].ImageName );
  508. SetRegistryString( hSubKey, REGVAL_PROVIDER_NAME, FaxReg->DeviceProviders[Index].ProviderName );
  509. return TRUE;
  510. }
  511. BOOL
  512. EnumRoutingMethods(
  513. HKEY hSubKey,
  514. LPWSTR SubKeyName,
  515. DWORD Index,
  516. LPVOID pvRoutingExtension
  517. )
  518. {
  519. PREG_ROUTING_EXTENSION RoutingExtension = (PREG_ROUTING_EXTENSION) pvRoutingExtension;
  520. if (SubKeyName == NULL) {
  521. if (Index) {
  522. RoutingExtension->RoutingMethods = (PREG_ROUTING_METHOD) MemAlloc( Index * sizeof(REG_ROUTING_METHOD) );
  523. if (!RoutingExtension->RoutingMethods) {
  524. return FALSE;
  525. }
  526. }
  527. return TRUE;
  528. }
  529. if (RoutingExtension == NULL || RoutingExtension->RoutingMethods == NULL) {
  530. return FALSE;
  531. }
  532. RoutingExtension->RoutingMethods[Index].InternalName = StringDup( SubKeyName );
  533. RoutingExtension->RoutingMethods[Index].FriendlyName = GetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, EMPTY_STRING );
  534. RoutingExtension->RoutingMethods[Index].FunctionName = GetRegistryString( hSubKey, REGVAL_FUNCTION_NAME, EMPTY_STRING );
  535. RoutingExtension->RoutingMethods[Index].Guid = GetRegistryString( hSubKey, REGVAL_GUID, EMPTY_STRING );
  536. RoutingExtension->RoutingMethods[Index].Priority = GetRegistryDword( hSubKey, REGVAL_ROUTING_PRIORITY );
  537. return TRUE;
  538. }
  539. BOOL
  540. EnumRoutingMethodsChange(
  541. HKEY hSubKey,
  542. LPWSTR SubKeyName,
  543. DWORD Index,
  544. LPVOID lpRoutingExtension
  545. )
  546. {
  547. PREG_ROUTING_EXTENSION RoutingExtension = (PREG_ROUTING_EXTENSION) lpRoutingExtension;
  548. if (SubKeyName == NULL) {
  549. //
  550. // called once for the subkey
  551. //
  552. return TRUE;
  553. }
  554. if (RoutingExtension == NULL || RoutingExtension->RoutingMethods) {
  555. return FALSE;
  556. }
  557. SetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, RoutingExtension->RoutingMethods[Index].FriendlyName );
  558. SetRegistryString( hSubKey, REGVAL_FUNCTION_NAME, RoutingExtension->RoutingMethods[Index].FunctionName );
  559. SetRegistryString( hSubKey, REGVAL_GUID, RoutingExtension->RoutingMethods[Index].Guid );
  560. SetRegistryDword ( hSubKey, REGVAL_ROUTING_PRIORITY, RoutingExtension->RoutingMethods[Index].Priority );
  561. return TRUE;
  562. }
  563. BOOL
  564. EnumRoutingExtensions(
  565. HKEY hSubKey,
  566. LPWSTR SubKeyName,
  567. DWORD Index,
  568. LPVOID lpFaxReg
  569. )
  570. {
  571. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  572. if (SubKeyName == NULL) {
  573. if (Index) {
  574. FaxReg->RoutingExtensions = (PREG_ROUTING_EXTENSION) MemAlloc( Index * sizeof(REG_ROUTING_EXTENSION) );
  575. if (!FaxReg->RoutingExtensions) {
  576. return FALSE;
  577. }
  578. }
  579. return TRUE;
  580. }
  581. if (FaxReg == NULL || FaxReg->RoutingExtensions == NULL) {
  582. return FALSE;
  583. }
  584. FaxReg->RoutingExtensions[Index].InternalName = StringDup( SubKeyName );
  585. FaxReg->RoutingExtensions[Index].FriendlyName = GetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, EMPTY_STRING );
  586. FaxReg->RoutingExtensions[Index].ImageName = GetRegistryStringExpand( hSubKey, REGVAL_IMAGE_NAME, EMPTY_STRING );
  587. //
  588. // load the routing methods for this extension
  589. //
  590. FaxReg->RoutingExtensions[Index].RoutingMethodsCount = EnumerateRegistryKeys(
  591. hSubKey,
  592. REGKEY_ROUTING_METHODS,
  593. FALSE,
  594. EnumRoutingMethods,
  595. &FaxReg->RoutingExtensions[Index]
  596. );
  597. return TRUE;
  598. }
  599. BOOL
  600. EnumRoutingExtensionsChange(
  601. HKEY hSubKey,
  602. LPWSTR SubKeyName,
  603. DWORD Index,
  604. LPVOID lpFaxReg
  605. )
  606. {
  607. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  608. if (SubKeyName == NULL) {
  609. //
  610. // called once for the subkey
  611. //
  612. return TRUE;
  613. }
  614. if (FaxReg == NULL || FaxReg->RoutingExtensions == NULL) {
  615. return FALSE;
  616. }
  617. SetRegistryString( hSubKey, REGVAL_FRIENDLY_NAME, FaxReg->RoutingExtensions[Index].FriendlyName );
  618. SetRegistryStringExpand( hSubKey, REGVAL_IMAGE_NAME, FaxReg->RoutingExtensions[Index].ImageName );
  619. //
  620. // load the routing methods for this extension
  621. //
  622. EnumerateRegistryKeys(
  623. hSubKey,
  624. REGKEY_ROUTING_METHODS,
  625. TRUE,
  626. EnumRoutingMethodsChange,
  627. &FaxReg->RoutingExtensions[Index]
  628. );
  629. return TRUE;
  630. }
  631. BOOL
  632. EnumDevices(
  633. HKEY hSubKey,
  634. LPWSTR SubKeyName,
  635. DWORD Index,
  636. LPVOID lpFaxReg
  637. )
  638. {
  639. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  640. HKEY hNewSubKey = NULL;
  641. if (SubKeyName == NULL) {
  642. if (Index) {
  643. FaxReg->Devices = (PREG_DEVICE) MemAlloc( Index * sizeof(REG_DEVICE) );
  644. if (!FaxReg->Devices) {
  645. return FALSE;
  646. }
  647. ZeroMemory(FaxReg->Devices, Index * sizeof(REG_DEVICE));
  648. }
  649. return TRUE;
  650. }
  651. if (FaxReg == NULL || FaxReg->Devices == NULL) {
  652. return FALSE;
  653. }
  654. FaxReg->Devices[Index].PermanentLineId = GetRegistryDword( hSubKey, REGVAL_PERMANENT_LINEID);
  655. hNewSubKey = OpenRegistryKey( hSubKey, REGKEY_FAXSVC_DEVICE_GUID, FALSE, NULL );
  656. if(hNewSubKey)
  657. {
  658. DWORDLONG *pTemp;
  659. DWORD dwDataSize = sizeof(DWORDLONG);
  660. FaxReg->Devices[Index].bValidDevice = TRUE;
  661. FaxReg->Devices[Index].Flags = GetRegistryDword( hNewSubKey, REGVAL_FLAGS );
  662. FaxReg->Devices[Index].Rings = GetRegistryDword( hNewSubKey, REGVAL_RINGS );
  663. FaxReg->Devices[Index].Name = GetRegistryString( hNewSubKey, REGVAL_DEVICE_NAME, EMPTY_STRING );
  664. FaxReg->Devices[Index].Csid = GetRegistryString( hNewSubKey, REGVAL_ROUTING_CSID, EMPTY_STRING );
  665. FaxReg->Devices[Index].Tsid = GetRegistryString( hNewSubKey, REGVAL_ROUTING_TSID, EMPTY_STRING );
  666. FaxReg->Devices[Index].TapiPermanentLineID = GetRegistryDword( hNewSubKey, REGVAL_TAPI_PERMANENT_LINEID );
  667. FaxReg->Devices[Index].lptstrDeviceName = GetRegistryString( hNewSubKey, REGVAL_DEVICE_NAME, EMPTY_STRING);
  668. FaxReg->Devices[Index].lptstrDescription = GetRegistryString( hNewSubKey, REGVAL_DEVICE_DESCRIPTION, EMPTY_STRING);
  669. FaxReg->Devices[Index].lptstrProviderGuid = GetRegistryString( hNewSubKey, REGVAL_PROVIDER_GUID, EMPTY_STRING );
  670. pTemp = (DWORDLONG *)GetRegistryBinary(hNewSubKey, REGVAL_LAST_DETECTED_TIME, &dwDataSize);
  671. if(pTemp && dwDataSize == sizeof(DWORDLONG))
  672. {
  673. FaxReg->Devices[Index].dwlLastDetected = *pTemp;
  674. MemFree(pTemp);
  675. }
  676. RegCloseKey(hNewSubKey);
  677. }
  678. else
  679. {
  680. FaxReg->Devices[Index].bValidDevice = FALSE;
  681. }
  682. return TRUE;
  683. }
  684. VOID
  685. SetDevicesValues(
  686. HKEY hSubKey,
  687. DWORD dwPermanentLineId,
  688. DWORD TapiPermanentLineID,
  689. DWORD Flags,
  690. DWORD Rings,
  691. LPCTSTR DeviceName,
  692. LPCTSTR ProviderGuid,
  693. LPCTSTR Csid,
  694. LPCTSTR Tsid
  695. )
  696. {
  697. HKEY hNewSubKey = NULL;
  698. SetRegistryDword( hSubKey, REGVAL_PERMANENT_LINEID, dwPermanentLineId );
  699. hNewSubKey = OpenRegistryKey( hSubKey, REGKEY_FAXSVC_DEVICE_GUID, TRUE, NULL );
  700. if(hNewSubKey)
  701. {
  702. SetRegistryDword( hNewSubKey, REGVAL_TAPI_PERMANENT_LINEID, TapiPermanentLineID );
  703. SetRegistryDword( hNewSubKey, REGVAL_FLAGS, Flags );
  704. SetRegistryDword( hNewSubKey, REGVAL_RINGS, Rings );
  705. if (DeviceName)
  706. {
  707. SetRegistryString( hNewSubKey, REGVAL_DEVICE_NAME, DeviceName );
  708. }
  709. if (ProviderGuid)
  710. {
  711. if (ProviderGuid[0])
  712. {
  713. SetRegistryString( hNewSubKey, REGVAL_PROVIDER_GUID, ProviderGuid );
  714. }
  715. }
  716. SetRegistryString( hNewSubKey, REGVAL_ROUTING_CSID, Csid );
  717. SetRegistryString( hNewSubKey, REGVAL_ROUTING_TSID, Tsid );
  718. RegCloseKey(hNewSubKey);
  719. }
  720. }
  721. BOOL
  722. EnumDevicesChange(
  723. HKEY hSubKey,
  724. LPWSTR SubKeyName,
  725. DWORD Index,
  726. LPVOID lpFaxReg
  727. )
  728. {
  729. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  730. if (SubKeyName == NULL) {
  731. //
  732. // called once for the subkey
  733. //
  734. return TRUE;
  735. }
  736. if (FaxReg == NULL || FaxReg->Devices == NULL) {
  737. return FALSE;
  738. }
  739. SetDevicesValues(
  740. hSubKey,
  741. FaxReg->Devices[Index].PermanentLineId,
  742. FaxReg->Devices[Index].TapiPermanentLineID,
  743. FaxReg->Devices[Index].Flags,
  744. FaxReg->Devices[Index].Rings,
  745. FaxReg->Devices[Index].Name,
  746. FaxReg->Devices[Index].lptstrProviderGuid,
  747. FaxReg->Devices[Index].Csid,
  748. FaxReg->Devices[Index].Tsid
  749. );
  750. return TRUE;
  751. }
  752. BOOL
  753. EnumLogging(
  754. HKEY hSubKey,
  755. LPWSTR SubKeyName,
  756. DWORD Index,
  757. LPVOID lpFaxReg
  758. )
  759. {
  760. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  761. if (SubKeyName == NULL)
  762. {
  763. if (Index)
  764. {
  765. FaxReg->Logging = (PREG_CATEGORY) MemAlloc( Index * sizeof(REG_CATEGORY) );
  766. if (!FaxReg->Logging)
  767. {
  768. return FALSE;
  769. }
  770. }
  771. return TRUE;
  772. }
  773. if (FaxReg->Logging == NULL)
  774. {
  775. return FALSE;
  776. }
  777. FaxReg->Logging[Index].CategoryName = GetRegistryString( hSubKey, REGVAL_CATEGORY_NAME, EMPTY_STRING );
  778. FaxReg->Logging[Index].Level = GetRegistryDword( hSubKey, REGVAL_CATEGORY_LEVEL );
  779. FaxReg->Logging[Index].Number = GetRegistryDword( hSubKey, REGVAL_CATEGORY_NUMBER );
  780. return TRUE;
  781. }
  782. BOOL
  783. EnumLoggingChange(
  784. HKEY hSubKey,
  785. LPWSTR SubKeyName,
  786. DWORD Index,
  787. LPVOID lpFaxReg
  788. )
  789. {
  790. PREG_FAX_SERVICE FaxReg = (PREG_FAX_SERVICE) lpFaxReg;
  791. if (SubKeyName == NULL) {
  792. return TRUE;
  793. }
  794. SetRegistryString( hSubKey, REGVAL_CATEGORY_NAME, FaxReg->Logging[Index].CategoryName );
  795. SetRegistryDword( hSubKey, REGVAL_CATEGORY_LEVEL, FaxReg->Logging[Index].Level );
  796. SetRegistryDword( hSubKey, REGVAL_CATEGORY_NUMBER, FaxReg->Logging[Index].Number );
  797. return TRUE;
  798. }
  799. DWORD
  800. GetFaxRegistry(
  801. PREG_FAX_SERVICE* ppFaxReg
  802. )
  803. {
  804. HKEY hKey;
  805. DWORD Tmp;
  806. DWORD ec;
  807. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ );
  808. if (!hKey)
  809. {
  810. ec = GetLastError();
  811. return ec;
  812. }
  813. if (NULL == *ppFaxReg)
  814. {
  815. //
  816. // First call - Allocate FaxReg and read only what is needed for event log
  817. //
  818. *ppFaxReg = (PREG_FAX_SERVICE) MemAlloc( sizeof(REG_FAX_SERVICE) );
  819. if (!*ppFaxReg)
  820. {
  821. RegCloseKey( hKey );
  822. return ERROR_OUTOFMEMORY;
  823. }
  824. ZeroMemory (*ppFaxReg, sizeof(REG_FAX_SERVICE));
  825. //
  826. // load the logging categories
  827. //
  828. (*ppFaxReg)->LoggingCount = EnumerateRegistryKeys(
  829. hKey,
  830. REGKEY_LOGGING,
  831. FALSE,
  832. EnumLogging,
  833. *ppFaxReg
  834. );
  835. RegCloseKey( hKey );
  836. return ERROR_SUCCESS;
  837. }
  838. //
  839. // load the fax service values
  840. //
  841. (*ppFaxReg)->Retries = GetRegistryDword( hKey, REGVAL_RETRIES );
  842. (*ppFaxReg)->RetryDelay = GetRegistryDword( hKey, REGVAL_RETRYDELAY );
  843. (*ppFaxReg)->DirtyDays = GetRegistryDword( hKey, REGVAL_DIRTYDAYS );
  844. (*ppFaxReg)->dwQueueState = GetRegistryDword (hKey, REGVAL_QUEUE_STATE);
  845. (*ppFaxReg)->NextJobNumber = GetRegistryDword( hKey, REGVAL_JOB_NUMBER );
  846. (*ppFaxReg)->Branding = GetRegistryDword( hKey, REGVAL_BRANDING );
  847. (*ppFaxReg)->UseDeviceTsid = GetRegistryDword( hKey, REGVAL_USE_DEVICE_TSID );
  848. (*ppFaxReg)->ServerCp = GetRegistryDword( hKey, REGVAL_SERVERCP );
  849. Tmp = GetRegistryDword( hKey, REGVAL_STARTCHEAP );
  850. (*ppFaxReg)->StartCheapTime.Hour = LOWORD(Tmp);
  851. (*ppFaxReg)->StartCheapTime.Minute = HIWORD(Tmp);
  852. Tmp = GetRegistryDword( hKey, REGVAL_STOPCHEAP );
  853. (*ppFaxReg)->StopCheapTime.Hour = LOWORD(Tmp);
  854. (*ppFaxReg)->StopCheapTime.Minute = HIWORD(Tmp);
  855. (*ppFaxReg)->dwLastUniqueLineId = GetRegistryDword( hKey, REGVAL_LAST_UNIQUE_LINE_ID );
  856. (*ppFaxReg)->dwMaxLineCloseTime = GetRegistryDword( hKey, REGVAL_MAX_LINE_CLOSE_TIME );
  857. (*ppFaxReg)->lptstrQueueDir = GetRegistryString( hKey, REGVAL_QUEUE_DIRECTORY, NULL );
  858. (*ppFaxReg)->dwRecipientsLimit = GetRegistryDword( hKey, REGVAL_RECIPIENTS_LIMIT );
  859. (*ppFaxReg)->dwAllowRemote = GetRegistryDword( hKey, REGVAL_ALLOW_REMOTE );
  860. //
  861. // load the device providers
  862. //
  863. (*ppFaxReg)->DeviceProviderCount = EnumerateRegistryKeys(
  864. hKey,
  865. REGKEY_DEVICE_PROVIDERS,
  866. FALSE,
  867. EnumDeviceProviders,
  868. *ppFaxReg
  869. );
  870. //
  871. // load the routing extensions
  872. //
  873. (*ppFaxReg)->RoutingExtensionsCount = EnumerateRegistryKeys(
  874. hKey,
  875. REGKEY_ROUTING_EXTENSIONS,
  876. FALSE,
  877. EnumRoutingExtensions,
  878. *ppFaxReg
  879. );
  880. //
  881. // load the devices
  882. //
  883. (*ppFaxReg)->DeviceCount = EnumerateRegistryKeys(
  884. hKey,
  885. REGKEY_DEVICES,
  886. FALSE,
  887. EnumDevices,
  888. *ppFaxReg
  889. );
  890. RegCloseKey( hKey );
  891. return ERROR_SUCCESS;
  892. }
  893. VOID
  894. FreeFaxRegistry(
  895. PREG_FAX_SERVICE FaxReg
  896. )
  897. {
  898. DWORD i,j;
  899. if (!FaxReg) {
  900. return;
  901. }
  902. for (i=0; i<FaxReg->DeviceProviderCount; i++) {
  903. MemFree( FaxReg->DeviceProviders[i].FriendlyName );
  904. MemFree( FaxReg->DeviceProviders[i].ImageName );
  905. MemFree( FaxReg->DeviceProviders[i].ProviderName );
  906. }
  907. for (i=0; i<FaxReg->RoutingExtensionsCount; i++) {
  908. MemFree( FaxReg->RoutingExtensions[i].FriendlyName );
  909. MemFree( FaxReg->RoutingExtensions[i].ImageName );
  910. for (j=0; j<FaxReg->RoutingExtensions[i].RoutingMethodsCount; j++) {
  911. MemFree( FaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName );
  912. MemFree( FaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName );
  913. MemFree( FaxReg->RoutingExtensions[i].RoutingMethods[j].Guid );
  914. }
  915. MemFree( FaxReg->RoutingExtensions[i].RoutingMethods );
  916. }
  917. MemFree( FaxReg->DeviceProviders );
  918. MemFree( FaxReg->RoutingExtensions );
  919. for (i=0; i<FaxReg->DeviceCount; i++) {
  920. MemFree( FaxReg->Devices[i].Name );
  921. }
  922. MemFree( FaxReg->Devices );
  923. for (i=0; i<FaxReg->LoggingCount; i++) {
  924. MemFree( FaxReg->Logging[i].CategoryName );
  925. }
  926. MemFree( FaxReg->Logging );
  927. MemFree( FaxReg->lptstrQueueDir );
  928. MemFree( FaxReg );
  929. }
  930. //
  931. // This functions is provided to support the legacy FaxSetConfiguration API call.
  932. //
  933. BOOL
  934. SetFaxGlobalsRegistry(
  935. PFAX_CONFIGURATION FaxConfig,
  936. DWORD dwQueueState
  937. )
  938. {
  939. DEBUG_FUNCTION_NAME(TEXT("SetFaxGlobalsRegistry"));
  940. DWORD dwRes = SaveQueueState (dwQueueState);
  941. if (ERROR_SUCCESS != dwRes)
  942. {
  943. SetLastError (dwRes);
  944. return FALSE;
  945. }
  946. HKEY hKey;
  947. HKEY hSentItemsArchiveKey;
  948. HKEY hReceiptsKey;
  949. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
  950. REGKEY_SOFTWARE,
  951. TRUE,
  952. KEY_WRITE );
  953. if (!hKey)
  954. {
  955. dwRes = GetLastError ();
  956. DebugPrintEx(
  957. DEBUG_ERR,
  958. TEXT("Can't open server's registry key : %ld"),
  959. dwRes);
  960. return FALSE;
  961. }
  962. hSentItemsArchiveKey = OpenRegistryKey( hKey,
  963. REGKEY_ARCHIVE_SENTITEMS_CONFIG,
  964. TRUE,
  965. KEY_WRITE );
  966. if (!hSentItemsArchiveKey)
  967. {
  968. dwRes = GetLastError ();
  969. DebugPrintEx(
  970. DEBUG_ERR,
  971. TEXT("Can't open server's sent items archive registry key : %ld"),
  972. dwRes);
  973. RegCloseKey( hKey );
  974. return FALSE;
  975. }
  976. hReceiptsKey = OpenRegistryKey( hKey,
  977. REGKEY_RECEIPTS_CONFIG,
  978. TRUE,
  979. KEY_WRITE );
  980. if (!hReceiptsKey)
  981. {
  982. dwRes = GetLastError ();
  983. DebugPrintEx(
  984. DEBUG_ERR,
  985. TEXT("Can't open server's Receipts registry key : %ld"),
  986. dwRes);
  987. RegCloseKey( hKey );
  988. RegCloseKey( hSentItemsArchiveKey );
  989. return FALSE;
  990. }
  991. SetRegistryDword( hKey, REGVAL_RETRIES, FaxConfig->Retries );
  992. SetRegistryDword( hKey, REGVAL_RETRYDELAY, FaxConfig->RetryDelay );
  993. SetRegistryDword( hKey, REGVAL_DIRTYDAYS, FaxConfig->DirtyDays );
  994. SetRegistryDword( hKey, REGVAL_BRANDING, FaxConfig->Branding );
  995. SetRegistryDword( hKey, REGVAL_USE_DEVICE_TSID, FaxConfig->UseDeviceTsid );
  996. SetRegistryDword( hKey, REGVAL_SERVERCP, FaxConfig->ServerCp );
  997. SetRegistryDword( hKey, REGVAL_STARTCHEAP, MAKELONG( FaxConfig->StartCheapTime.Hour, FaxConfig->StartCheapTime.Minute ) );
  998. SetRegistryDword( hKey, REGVAL_STOPCHEAP, MAKELONG( FaxConfig->StopCheapTime.Hour, FaxConfig->StopCheapTime.Minute ) );
  999. SetRegistryDword( hSentItemsArchiveKey,
  1000. REGVAL_ARCHIVE_USE,
  1001. FaxConfig->ArchiveOutgoingFaxes);
  1002. SetRegistryString( hSentItemsArchiveKey,
  1003. REGVAL_ARCHIVE_FOLDER,
  1004. FaxConfig->ArchiveDirectory );
  1005. RegCloseKey( hReceiptsKey );
  1006. RegCloseKey( hSentItemsArchiveKey );
  1007. RegCloseKey( hKey );
  1008. return TRUE;
  1009. }
  1010. /******************************************************************************
  1011. * Name: SetFaxJobNumberRegistry
  1012. * Author:
  1013. *******************************************************************************
  1014. DESCRIPTION:
  1015. Saves the value of the next job id to the registry at the
  1016. REGKEY_FAXSERVER\NextJobId value.
  1017. PARAMETERS:
  1018. NextJobNumber
  1019. A DWORD value of the next job id.
  1020. RETURN VALUE:
  1021. TRUE if no error occured.
  1022. FALSE otherwise.
  1023. REMARKS:
  1024. NONE.
  1025. *******************************************************************************/
  1026. BOOL
  1027. SetFaxJobNumberRegistry(
  1028. DWORD NextJobNumber
  1029. )
  1030. {
  1031. HKEY hKey;
  1032. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, TRUE, KEY_WRITE );
  1033. if (!hKey) {
  1034. return FALSE;
  1035. }
  1036. SetRegistryDword( hKey, REGVAL_JOB_NUMBER, NextJobNumber );
  1037. RegCloseKey( hKey );
  1038. return TRUE;
  1039. }
  1040. BOOL
  1041. GetLoggingCategoriesRegistry(
  1042. PREG_FAX_LOGGING FaxRegLogging
  1043. )
  1044. {
  1045. REG_FAX_SERVICE FaxReg = {0};
  1046. HKEY hKey;
  1047. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ );
  1048. if (!hKey) {
  1049. return FALSE;
  1050. }
  1051. FaxRegLogging->LoggingCount = EnumerateRegistryKeys(
  1052. hKey,
  1053. REGKEY_LOGGING,
  1054. FALSE,
  1055. EnumLogging,
  1056. &FaxReg
  1057. );
  1058. RegCloseKey( hKey );
  1059. FaxRegLogging->Logging = FaxReg.Logging;
  1060. return TRUE;
  1061. }
  1062. BOOL
  1063. SetLoggingCategoriesRegistry(
  1064. PREG_FAX_LOGGING FaxRegLogging
  1065. )
  1066. {
  1067. REG_FAX_SERVICE FaxReg = {0};
  1068. HKEY hKey;
  1069. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, TRUE, KEY_READ | KEY_WRITE );
  1070. if (!hKey) {
  1071. return FALSE;
  1072. }
  1073. FaxReg.Logging = FaxRegLogging->Logging;
  1074. FaxReg.LoggingCount = FaxRegLogging->LoggingCount;
  1075. EnumerateRegistryKeys(
  1076. hKey,
  1077. REGKEY_LOGGING,
  1078. TRUE,
  1079. EnumLoggingChange,
  1080. &FaxReg
  1081. );
  1082. RegCloseKey( hKey );
  1083. return TRUE;
  1084. }
  1085. PREG_FAX_DEVICES
  1086. GetFaxDevicesRegistry(
  1087. VOID
  1088. )
  1089. {
  1090. PREG_FAX_SERVICE FaxReg;
  1091. PREG_FAX_DEVICES FaxRegDevices;
  1092. HKEY hKey;
  1093. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ );
  1094. if (!hKey) {
  1095. return NULL;
  1096. }
  1097. FaxReg = (PREG_FAX_SERVICE) MemAlloc( sizeof(REG_FAX_SERVICE) );
  1098. if (!FaxReg) {
  1099. RegCloseKey( hKey );
  1100. return NULL;
  1101. }
  1102. FaxRegDevices = (PREG_FAX_DEVICES) MemAlloc( sizeof(REG_FAX_DEVICES) );
  1103. if (!FaxRegDevices) {
  1104. MemFree( FaxReg );
  1105. RegCloseKey( hKey );
  1106. return NULL;
  1107. }
  1108. //
  1109. // load the devices
  1110. //
  1111. FaxReg->DeviceCount = EnumerateRegistryKeys(
  1112. hKey,
  1113. REGKEY_DEVICES,
  1114. FALSE,
  1115. EnumDevices,
  1116. FaxReg
  1117. );
  1118. RegCloseKey( hKey );
  1119. FaxRegDevices->Devices = FaxReg->Devices;
  1120. FaxRegDevices->DeviceCount = FaxReg->DeviceCount;
  1121. MemFree( FaxReg );
  1122. return FaxRegDevices;
  1123. }
  1124. //
  1125. // Note: This function requires mutual execlusion. Use CsLine to sync access to it.
  1126. //
  1127. DWORD
  1128. RegAddNewFaxDevice(
  1129. LPDWORD lpdwLastUniqueLineId,
  1130. LPDWORD lpdwPermanentLineId,
  1131. LPTSTR DeviceName,
  1132. LPTSTR ProviderName,
  1133. LPTSTR ProviderGuid,
  1134. LPTSTR Csid,
  1135. LPTSTR Tsid,
  1136. DWORD TapiPermanentLineID,
  1137. DWORD Flags,
  1138. DWORD Rings
  1139. )
  1140. {
  1141. HKEY hKey;
  1142. TCHAR SubKeyName[128];
  1143. DWORD dwNewUniqueLineId;
  1144. DWORD dwAttempt = 0;
  1145. DWORD dwRes = ERROR_SUCCESS;
  1146. DEBUG_FUNCTION_NAME(TEXT("RegAddNewFaxDevice"));
  1147. Assert( lpdwLastUniqueLineId);
  1148. Assert( lpdwPermanentLineId);
  1149. if (0 == *(lpdwPermanentLineId))
  1150. {
  1151. if( ERROR_SUCCESS != GetNewServiceDeviceID(lpdwLastUniqueLineId,lpdwPermanentLineId) )
  1152. {
  1153. DebugPrintEx(
  1154. DEBUG_ERR,
  1155. TEXT("Failed to generate next uniqueu line id."));
  1156. return E_FAIL;
  1157. }
  1158. }
  1159. //
  1160. // The caller provider the unique line id. This is an update operation.
  1161. //
  1162. dwNewUniqueLineId = *lpdwPermanentLineId;
  1163. //
  1164. // create the device's registry key
  1165. //
  1166. _stprintf( SubKeyName, TEXT("%s\\%010d"), REGKEY_FAX_DEVICES, dwNewUniqueLineId );
  1167. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, TRUE, KEY_WRITE );
  1168. if (!hKey) {
  1169. dwRes = GetLastError();
  1170. DebugPrintEx(
  1171. DEBUG_ERR,
  1172. TEXT("OpenRegistryKey failed for [%s] (ec: %ld)"),
  1173. SubKeyName,
  1174. dwRes);
  1175. return dwRes;
  1176. }
  1177. SetDevicesValues(
  1178. hKey,
  1179. *lpdwPermanentLineId,
  1180. TapiPermanentLineID,
  1181. Flags,
  1182. Rings,
  1183. DeviceName,
  1184. ProviderGuid,
  1185. Csid,
  1186. Tsid
  1187. );
  1188. RegCloseKey( hKey );
  1189. //
  1190. // close the handles and leave
  1191. //
  1192. return dwRes;
  1193. }
  1194. DWORD
  1195. RegSetFaxDeviceFlags(
  1196. DWORD dwPermanentLineID,
  1197. DWORD dwFlags
  1198. )
  1199. {
  1200. HKEY hKey;
  1201. TCHAR SubKeyName[256] = {0};
  1202. DWORD dwRes = ERROR_SUCCESS;
  1203. DEBUG_FUNCTION_NAME(TEXT("RegSetFaxDeviceFlags"));
  1204. //
  1205. // Open the device's registry key
  1206. //
  1207. _sntprintf( SubKeyName,
  1208. ARR_SIZE(SubKeyName) - 1,
  1209. TEXT("%s\\%010d\\%s"),
  1210. REGKEY_FAX_DEVICES,
  1211. dwPermanentLineID,
  1212. REGKEY_FAXSVC_DEVICE_GUID);
  1213. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, FALSE, KEY_WRITE );
  1214. if (NULL == hKey)
  1215. {
  1216. dwRes = GetLastError();
  1217. DebugPrintEx(
  1218. DEBUG_ERR,
  1219. TEXT("OpenRegistryKey failed for [%s] (ec: %ld)"),
  1220. SubKeyName,
  1221. dwRes);
  1222. return dwRes;
  1223. }
  1224. if (!SetRegistryDword(hKey, REGVAL_FLAGS, dwFlags))
  1225. {
  1226. dwRes = GetLastError();
  1227. DebugPrintEx(
  1228. DEBUG_ERR,
  1229. TEXT("SetRegistryDword failed (ec: %ld)"),
  1230. dwRes);
  1231. }
  1232. RegCloseKey( hKey );
  1233. //
  1234. // close the handles and leave
  1235. //
  1236. return dwRes;
  1237. }
  1238. BOOL
  1239. SetFaxRoutingInfo(
  1240. LPTSTR ExtensionName,
  1241. LPTSTR MethodName,
  1242. LPTSTR Guid,
  1243. DWORD Priority,
  1244. LPTSTR FunctionName,
  1245. LPTSTR FriendlyName
  1246. )
  1247. {
  1248. HKEY hKey;
  1249. LPTSTR KeyName = NULL;
  1250. // calculate string size and allocate memory.
  1251. // the string sizes includes the terminating NULL which is replaced with '\\' and terminating NULL of the KeyName String
  1252. KeyName = (LPTSTR) MemAlloc( StringSize(REGKEY_ROUTING_EXTENSION_KEY) +
  1253. StringSize(ExtensionName) +
  1254. StringSize(REGKEY_ROUTING_METHODS) +
  1255. StringSize(MethodName)
  1256. );
  1257. if ( !KeyName )
  1258. return FALSE;
  1259. wsprintf( KeyName, L"%s\\%s\\%s\\%s", REGKEY_ROUTING_EXTENSION_KEY, ExtensionName,REGKEY_ROUTING_METHODS, MethodName );
  1260. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, KeyName, FALSE, KEY_WRITE );
  1261. if (!hKey) {
  1262. MemFree( KeyName );
  1263. return FALSE;
  1264. }
  1265. MemFree ( KeyName );
  1266. SetRegistryString( hKey, REGVAL_FRIENDLY_NAME, FriendlyName );
  1267. SetRegistryString( hKey, REGVAL_FUNCTION_NAME, FunctionName );
  1268. SetRegistryString( hKey, REGVAL_GUID, Guid );
  1269. SetRegistryDword ( hKey, REGVAL_ROUTING_PRIORITY, Priority );
  1270. RegCloseKey( hKey );
  1271. return TRUE;
  1272. }
  1273. BOOL
  1274. DeleteFaxDevice(
  1275. DWORD PermanentLineID,
  1276. DWORD TapiPermanentLineID
  1277. )
  1278. {
  1279. BOOL success = TRUE;
  1280. TCHAR SubKey[512];
  1281. // delete any extension configuration data
  1282. _stprintf( SubKey, TEXT("%s\\%08x"), REGKEY_TAPIDEVICES, TapiPermanentLineID );
  1283. if(!DeleteRegistryKey( HKEY_LOCAL_MACHINE, SubKey ))
  1284. success = FALSE;
  1285. // delete any device data
  1286. _stprintf( SubKey, TEXT("%s\\%s\\%010d"), REGKEY_SOFTWARE, REGKEY_DEVICES, PermanentLineID);
  1287. if(!DeleteRegistryKey( HKEY_LOCAL_MACHINE, SubKey ))
  1288. success = FALSE;
  1289. return success;
  1290. }
  1291. VOID
  1292. FreeFaxDevicesRegistry(
  1293. PREG_FAX_DEVICES FaxReg
  1294. )
  1295. {
  1296. DWORD i;
  1297. if (!FaxReg) {
  1298. return;
  1299. }
  1300. for (i=0; i<FaxReg->DeviceCount; i++) {
  1301. MemFree( FaxReg->Devices[i].Name );
  1302. }
  1303. MemFree( FaxReg->Devices );
  1304. MemFree( FaxReg );
  1305. }
  1306. BOOL
  1307. CreateFaxEventSource(
  1308. PREG_FAX_SERVICE FaxReg,
  1309. PFAX_LOG_CATEGORY DefaultCategories,
  1310. int DefaultCategoryCount
  1311. )
  1312. {
  1313. HKEY hKey;
  1314. HKEY hKeyLogging;
  1315. DWORD i;
  1316. DEBUG_FUNCTION_NAME(TEXT("CreateFaxEventSource"));
  1317. if (FaxReg->LoggingCount == 0)
  1318. {
  1319. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_LOGGING, TRUE, KEY_WRITE );
  1320. if (!hKey)
  1321. {
  1322. DebugPrintEx(
  1323. DEBUG_ERR,
  1324. TEXT("OpenRegistryKey failed with %ld."),
  1325. GetLastError ());
  1326. return FALSE;
  1327. }
  1328. FaxReg->Logging = (PREG_CATEGORY) MemAlloc(DefaultCategoryCount * sizeof(REG_CATEGORY) );
  1329. if (!FaxReg->Logging)
  1330. {
  1331. DebugPrintEx(
  1332. DEBUG_ERR,
  1333. TEXT("MemAlloc (%ld) failed."),
  1334. DefaultCategoryCount * sizeof(REG_CATEGORY));
  1335. RegCloseKey( hKey );
  1336. return FALSE;
  1337. }
  1338. for (i=0; i< (DWORD) DefaultCategoryCount; i++)
  1339. {
  1340. TCHAR szKeyName[16] = {0};
  1341. _itot(i+1,szKeyName,10);
  1342. hKeyLogging = OpenRegistryKey( hKey, szKeyName, TRUE, KEY_WRITE );
  1343. if (hKeyLogging)
  1344. {
  1345. SetRegistryString( hKeyLogging, REGVAL_CATEGORY_NAME, DefaultCategories[i].Name );
  1346. FaxReg->Logging[i].CategoryName = StringDup( DefaultCategories[i].Name);
  1347. SetRegistryDword( hKeyLogging, REGVAL_CATEGORY_LEVEL, DefaultCategories[i].Level );
  1348. FaxReg->Logging[i].Level = DefaultCategories[i].Level;
  1349. SetRegistryDword( hKeyLogging, REGVAL_CATEGORY_NUMBER, DefaultCategories[i].Category );
  1350. FaxReg->Logging[i].Number = DefaultCategories[i].Category;
  1351. RegCloseKey( hKeyLogging );
  1352. }
  1353. }
  1354. FaxReg->LoggingCount = DefaultCategoryCount;
  1355. RegCloseKey( hKey );
  1356. }
  1357. return TRUE;
  1358. }
  1359. BOOL
  1360. GetInstallationInfo(
  1361. LPDWORD Installed,
  1362. LPDWORD InstallType,
  1363. LPDWORD InstalledPlatforms,
  1364. LPDWORD ProductType
  1365. )
  1366. {
  1367. HKEY hKey;
  1368. LONG rVal;
  1369. DWORD RegType;
  1370. DWORD RegSize;
  1371. TCHAR ProductTypeStr[32];
  1372. DWORD Bytes;
  1373. DWORD Type;
  1374. if (Installed == NULL || InstallType == NULL || InstalledPlatforms == NULL || ProductType == NULL) {
  1375. return FALSE;
  1376. }
  1377. rVal = RegOpenKeyEx(
  1378. HKEY_LOCAL_MACHINE,
  1379. REGKEY_FAX_SETUP,
  1380. 0,
  1381. KEY_READ,
  1382. &hKey
  1383. );
  1384. if (rVal != ERROR_SUCCESS) {
  1385. DebugPrint(( TEXT("Could not open setup registry key, ec=0x%08x"), rVal ));
  1386. return FALSE;
  1387. }
  1388. RegSize = sizeof(DWORD);
  1389. rVal = RegQueryValueEx(
  1390. hKey,
  1391. REGVAL_FAXINSTALLED,
  1392. 0,
  1393. &RegType,
  1394. (LPBYTE) Installed,
  1395. &RegSize
  1396. );
  1397. if (rVal != ERROR_SUCCESS) {
  1398. DebugPrint(( TEXT("Could not query installed registry value, ec=0x%08x"), rVal ));
  1399. *Installed = 0;
  1400. }
  1401. rVal = RegQueryValueEx(
  1402. hKey,
  1403. REGVAL_FAXINSTALL_TYPE,
  1404. 0,
  1405. &RegType,
  1406. (LPBYTE) InstallType,
  1407. &RegSize
  1408. );
  1409. if (rVal != ERROR_SUCCESS) {
  1410. DebugPrint(( TEXT("Could not query install type registry value, ec=0x%08x"), rVal ));
  1411. *InstallType = 0;
  1412. }
  1413. rVal = RegQueryValueEx(
  1414. hKey,
  1415. REGVAL_FAXINSTALLED_PLATFORMS,
  1416. 0,
  1417. &RegType,
  1418. (LPBYTE) InstalledPlatforms,
  1419. &RegSize
  1420. );
  1421. if (rVal != ERROR_SUCCESS) {
  1422. DebugPrint(( TEXT("Could not query install platforms mask registry value, ec=0x%08x"), rVal ));
  1423. *InstalledPlatforms = 0;
  1424. }
  1425. RegCloseKey( hKey );
  1426. //
  1427. // get the product type
  1428. //
  1429. *ProductType = PRODUCT_TYPE_WINNT;
  1430. rVal = RegOpenKeyEx(
  1431. HKEY_LOCAL_MACHINE,
  1432. TEXT("System\\CurrentControlSet\\Control\\ProductOptions"),
  1433. 0,
  1434. KEY_READ,
  1435. &hKey
  1436. );
  1437. if (rVal == ERROR_SUCCESS) {
  1438. Bytes = sizeof(ProductTypeStr);
  1439. rVal = RegQueryValueEx(
  1440. hKey,
  1441. TEXT("ProductType"),
  1442. NULL,
  1443. &Type,
  1444. (LPBYTE) ProductTypeStr,
  1445. &Bytes
  1446. );
  1447. if (rVal == ERROR_SUCCESS) {
  1448. if ((_tcsicmp( ProductTypeStr, TEXT("SERVERNT") ) == 0) ||
  1449. (_tcsicmp( ProductTypeStr, TEXT("LANMANNT") ) == 0)) {
  1450. *ProductType = PRODUCT_TYPE_SERVER;
  1451. }
  1452. }
  1453. RegCloseKey( hKey );
  1454. }
  1455. return TRUE;
  1456. }
  1457. BOOL
  1458. IsModemClass1(
  1459. LPSTR SubKey,
  1460. LPBOOL Class1Fax
  1461. )
  1462. {
  1463. BOOL rVal = TRUE;
  1464. LONG Rslt;
  1465. HKEY hKey;
  1466. DWORD Type;
  1467. DWORD Size;
  1468. *Class1Fax = 0;
  1469. Rslt = RegOpenKeyExA(
  1470. HKEY_LOCAL_MACHINE,
  1471. SubKey,
  1472. 0,
  1473. KEY_READ,
  1474. &hKey
  1475. );
  1476. if (Rslt == ERROR_SUCCESS) {
  1477. Size = sizeof(DWORD);
  1478. Rslt = RegQueryValueEx(
  1479. hKey,
  1480. TEXT("FaxClass1"),
  1481. 0,
  1482. &Type,
  1483. (LPBYTE) Class1Fax,
  1484. &Size
  1485. );
  1486. if (Rslt != ERROR_SUCCESS) {
  1487. rVal = FALSE;
  1488. }
  1489. RegCloseKey( hKey );
  1490. }
  1491. return rVal;
  1492. }
  1493. BOOL
  1494. SaveModemClass(
  1495. LPSTR SubKey,
  1496. BOOL Class1Fax
  1497. )
  1498. {
  1499. BOOL rVal = FALSE;
  1500. LONG Rslt;
  1501. HKEY hKey;
  1502. Rslt = RegOpenKeyExA(
  1503. HKEY_LOCAL_MACHINE,
  1504. SubKey,
  1505. 0,
  1506. KEY_WRITE,
  1507. &hKey
  1508. );
  1509. if (Rslt == ERROR_SUCCESS) {
  1510. Rslt = RegSetValueEx(
  1511. hKey,
  1512. TEXT("FaxClass1"),
  1513. 0,
  1514. REG_DWORD,
  1515. (LPBYTE) &Class1Fax,
  1516. sizeof(DWORD)
  1517. );
  1518. if (Rslt == ERROR_SUCCESS) {
  1519. rVal = TRUE;
  1520. }
  1521. RegCloseKey( hKey );
  1522. }
  1523. return rVal;
  1524. }
  1525. BOOL
  1526. GetOrigSetupData(
  1527. IN DWORD dwPermanentLineId,
  1528. OUT PREG_SETUP RegSetup
  1529. )
  1530. /*++
  1531. Routine name : GetOrigSetupData
  1532. Routine description:
  1533. Read from the Registry Device's data. At upgrades, Setup writes some Devices's data,
  1534. and this function reads this and fills RegSetup.
  1535. Devices are recognized by their Permanent Line Id, which should not change during the
  1536. upgrade. After a specific device information is read, the key is deleted.
  1537. Author:
  1538. Iv Garber (IvG), Mar, 2001
  1539. Arguments:
  1540. dwPermanentLineId [IN] - Permanent Line Id of the Device
  1541. RegSetup [OUT] - the structure to be returned
  1542. Return Value:
  1543. TRUE if succeded, FALSE otherwise.
  1544. --*/
  1545. {
  1546. HKEY hKey = NULL;
  1547. BOOL fDeviceKey = TRUE;
  1548. TCHAR tszKeyName[256] = {0};
  1549. DEBUG_FUNCTION_NAME(TEXT("GetOrigSetupData"));
  1550. //
  1551. // see if some data is stored for this Permanent Line Id
  1552. //
  1553. _stprintf(tszKeyName, TEXT("%s\\%010d"), REGKEY_FAX_SETUP_ORIG, dwPermanentLineId);
  1554. hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, tszKeyName, FALSE, KEY_READ);
  1555. if (!hKey)
  1556. {
  1557. //
  1558. // This Permanent Line Id is new, so take default values
  1559. //
  1560. fDeviceKey = FALSE;
  1561. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP_ORIG, FALSE, KEY_READ);
  1562. if (!hKey)
  1563. {
  1564. //
  1565. // Registry is corrupted
  1566. //
  1567. DebugPrintEx(
  1568. DEBUG_ERR,
  1569. TEXT("Cann't open key SETUP_ORIG, ec = %ld"),
  1570. GetLastError());
  1571. return FALSE;
  1572. }
  1573. }
  1574. RegSetup->lptstrDescription = StringDup(EMPTY_STRING);
  1575. RegSetup->Csid = GetRegistryString(hKey, REGVAL_ROUTING_CSID, REGVAL_DEFAULT_CSID);
  1576. RegSetup->Tsid = GetRegistryString(hKey, REGVAL_ROUTING_TSID, REGVAL_DEFAULT_TSID);
  1577. RegSetup->Rings = GetRegistryDword(hKey, REGVAL_RINGS);
  1578. RegSetup->Flags = GetRegistryDword(hKey, REGVAL_FLAGS);
  1579. RegCloseKey(hKey);
  1580. //
  1581. // Delete the key if it is a key of a device after upgrade from W2K.
  1582. //
  1583. if (TRUE == fDeviceKey)
  1584. {
  1585. DWORD dwRes = RegDeleteKey (HKEY_LOCAL_MACHINE, tszKeyName);
  1586. if (ERROR_SUCCESS != dwRes)
  1587. {
  1588. DebugPrintEx(
  1589. DEBUG_ERR,
  1590. TEXT("RegDeleteKey failed, error %ld"),
  1591. dwRes);
  1592. }
  1593. }
  1594. return TRUE;
  1595. }
  1596. VOID
  1597. FreeOrigSetupData(
  1598. PREG_SETUP RegSetup
  1599. )
  1600. {
  1601. MemFree( RegSetup->Csid );
  1602. MemFree( RegSetup->Tsid );
  1603. MemFree( RegSetup->lptstrDescription );
  1604. }
  1605. DWORD
  1606. SaveQueueState (
  1607. DWORD dwNewState
  1608. )
  1609. /*++
  1610. Routine name : SaveQueueState
  1611. Routine description:
  1612. Saves the queue state bits to the registry
  1613. Author:
  1614. Eran Yariv (EranY), Nov, 1999
  1615. Arguments:
  1616. dwNewState [in] - New state to save
  1617. Return Value:
  1618. Standard Win32 error codes
  1619. --*/
  1620. {
  1621. HKEY hKey;
  1622. DWORD dwRes;
  1623. DEBUG_FUNCTION_NAME(TEXT("SaveQueueState"));
  1624. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_WRITE );
  1625. if (!hKey)
  1626. {
  1627. dwRes = GetLastError ();
  1628. DebugPrintEx(
  1629. DEBUG_ERR,
  1630. TEXT("Can't open key : %ld"),
  1631. dwRes);
  1632. return dwRes;
  1633. }
  1634. //
  1635. // Set the fax queue value
  1636. //
  1637. if (!SetRegistryDword( hKey, REGVAL_QUEUE_STATE, dwNewState))
  1638. {
  1639. dwRes = GetLastError ();
  1640. DebugPrintEx(
  1641. DEBUG_ERR,
  1642. TEXT("Can't write value : %ld"),
  1643. dwRes);
  1644. RegCloseKey( hKey );
  1645. return dwRes;
  1646. }
  1647. RegCloseKey( hKey );
  1648. return ERROR_SUCCESS;
  1649. } // SaveQueueState
  1650. DWORD
  1651. StoreReceiptsSettings (
  1652. CONST PFAX_RECEIPTS_CONFIG pReceiptsConfig
  1653. )
  1654. /*++
  1655. Routine name : StoreReceiptsSettings
  1656. Routine description:
  1657. Stores Receipts configuration in the registry.
  1658. Create the Receipts subkey if not existent.
  1659. Author:
  1660. Eran Yariv (EranY), Nov, 1999
  1661. Arguments:
  1662. pReceiptsConfig [in] - Receipts configuration to store
  1663. Return Value:
  1664. Standard Win32 error code
  1665. --*/
  1666. {
  1667. DWORD dwRes = ERROR_SUCCESS;
  1668. HKEY hServerKey = NULL;
  1669. HKEY hReceiptsKey = NULL;
  1670. DEBUG_FUNCTION_NAME(TEXT("StoreReceiptsSettings"));
  1671. hServerKey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
  1672. REGKEY_SOFTWARE,
  1673. FALSE,
  1674. KEY_WRITE );
  1675. if (NULL == hServerKey)
  1676. {
  1677. dwRes = GetLastError ();
  1678. DebugPrintEx(
  1679. DEBUG_ERR,
  1680. TEXT("Can't open key : %ld"),
  1681. dwRes);
  1682. return dwRes;
  1683. }
  1684. dwRes = RegCreateKey (hServerKey, REGKEY_RECEIPTS_CONFIG, &hReceiptsKey);
  1685. if (ERROR_SUCCESS != dwRes)
  1686. {
  1687. DebugPrintEx(
  1688. DEBUG_ERR,
  1689. TEXT("Can't create or open key : %ld"),
  1690. dwRes);
  1691. goto exit;
  1692. }
  1693. if (!SetRegistryDword( hReceiptsKey, REGVAL_ISFOR_MSROUTE, pReceiptsConfig->bIsToUseForMSRouteThroughEmailMethod))
  1694. {
  1695. dwRes = GetLastError ();
  1696. DebugPrintEx(
  1697. DEBUG_ERR,
  1698. TEXT("Can't write value : %ld"),
  1699. dwRes);
  1700. goto exit;
  1701. }
  1702. if (!SetRegistryDword( hReceiptsKey, REGVAL_RECEIPTS_TYPE, pReceiptsConfig->dwAllowedReceipts))
  1703. {
  1704. dwRes = GetLastError ();
  1705. DebugPrintEx(
  1706. DEBUG_ERR,
  1707. TEXT("Can't write value : %ld"),
  1708. dwRes);
  1709. goto exit;
  1710. }
  1711. if(
  1712. (pReceiptsConfig->dwAllowedReceipts & DRT_EMAIL)
  1713. ||
  1714. pReceiptsConfig->bIsToUseForMSRouteThroughEmailMethod
  1715. )
  1716. {
  1717. if (!SetRegistryDword( hReceiptsKey, REGVAL_RECEIPTS_PORT, pReceiptsConfig->dwSMTPPort))
  1718. {
  1719. dwRes = GetLastError ();
  1720. DebugPrintEx(
  1721. DEBUG_ERR,
  1722. TEXT("Can't write value : %ld"),
  1723. dwRes);
  1724. goto exit;
  1725. }
  1726. if (!SetRegistryDword( hReceiptsKey, REGVAL_RECEIPTS_SMTP_AUTH_TYPE, pReceiptsConfig->SMTPAuthOption))
  1727. {
  1728. dwRes = GetLastError ();
  1729. DebugPrintEx(
  1730. DEBUG_ERR,
  1731. TEXT("Can't write value : %ld"),
  1732. dwRes);
  1733. goto exit;
  1734. }
  1735. if (!SetRegistryString( hReceiptsKey,
  1736. REGVAL_RECEIPTS_SERVER,
  1737. pReceiptsConfig->lptstrSMTPServer ?
  1738. pReceiptsConfig->lptstrSMTPServer :
  1739. EMPTY_STRING))
  1740. {
  1741. dwRes = GetLastError ();
  1742. DebugPrintEx(
  1743. DEBUG_ERR,
  1744. TEXT("Can't write value : %ld"),
  1745. dwRes);
  1746. goto exit;
  1747. }
  1748. if (!SetRegistryString( hReceiptsKey,
  1749. REGVAL_RECEIPTS_FROM,
  1750. pReceiptsConfig->lptstrSMTPFrom ?
  1751. pReceiptsConfig->lptstrSMTPFrom : EMPTY_STRING))
  1752. {
  1753. dwRes = GetLastError ();
  1754. DebugPrintEx(
  1755. DEBUG_ERR,
  1756. TEXT("Can't write value : %ld"),
  1757. dwRes);
  1758. goto exit;
  1759. }
  1760. if (!SetRegistryString( hReceiptsKey,
  1761. REGVAL_RECEIPTS_USER,
  1762. pReceiptsConfig->lptstrSMTPUserName ?
  1763. pReceiptsConfig->lptstrSMTPUserName : EMPTY_STRING))
  1764. {
  1765. dwRes = GetLastError ();
  1766. DebugPrintEx(
  1767. DEBUG_ERR,
  1768. TEXT("Can't write value : %ld"),
  1769. dwRes);
  1770. goto exit;
  1771. }
  1772. if (pReceiptsConfig->lptstrSMTPPassword)
  1773. {
  1774. if (!SetRegistrySecureString(
  1775. hReceiptsKey,
  1776. REGVAL_RECEIPTS_PASSWORD,
  1777. pReceiptsConfig->lptstrSMTPPassword ?
  1778. pReceiptsConfig->lptstrSMTPPassword : EMPTY_STRING,
  1779. TRUE // Optionally non-encrypted
  1780. ))
  1781. {
  1782. dwRes = GetLastError ();
  1783. DebugPrintEx(
  1784. DEBUG_ERR,
  1785. TEXT("Can't write value : %ld"),
  1786. dwRes);
  1787. goto exit;
  1788. }
  1789. }
  1790. }
  1791. Assert (ERROR_SUCCESS == dwRes);
  1792. exit:
  1793. if (NULL != hReceiptsKey)
  1794. {
  1795. RegCloseKey (hReceiptsKey);
  1796. }
  1797. if (NULL != hServerKey)
  1798. {
  1799. RegCloseKey (hServerKey);
  1800. }
  1801. return dwRes;
  1802. } // StoreReceiptsSettings
  1803. DWORD
  1804. LoadReceiptsSettings (
  1805. PFAX_SERVER_RECEIPTS_CONFIGW pReceiptsConfig
  1806. )
  1807. /*++
  1808. Routine name : LoadReceiptsSettings
  1809. Routine description:
  1810. Reads Receipts configuration from the registry.
  1811. Ovverride destination strings without freeing anything.
  1812. Author:
  1813. Eran Yariv (EranY), Nov, 1999
  1814. Arguments:
  1815. pReceiptsConfig [out] - Receipts configuration to read
  1816. Return Value:
  1817. Standard Win32 error code
  1818. --*/
  1819. {
  1820. DWORD dwRes = ERROR_SUCCESS;
  1821. HKEY hReceiptsKey = NULL;
  1822. DEBUG_FUNCTION_NAME(TEXT("LoadReceiptsSettings"));
  1823. hReceiptsKey = OpenRegistryKey(
  1824. HKEY_LOCAL_MACHINE,
  1825. REGKEY_SOFTWARE TEXT("\\") REGKEY_RECEIPTS_CONFIG,
  1826. FALSE,
  1827. KEY_READ | KEY_WRITE );
  1828. if (NULL == hReceiptsKey)
  1829. {
  1830. dwRes = GetLastError ();
  1831. DebugPrintEx(
  1832. DEBUG_ERR,
  1833. TEXT("Can't open key : %ld"),
  1834. dwRes);
  1835. return dwRes;
  1836. }
  1837. pReceiptsConfig->dwSMTPPort = GetRegistryDword (hReceiptsKey, REGVAL_RECEIPTS_PORT);
  1838. if (0 == pReceiptsConfig->dwSMTPPort)
  1839. {
  1840. //
  1841. // A zero port is invalid
  1842. //
  1843. dwRes = GetLastError ();
  1844. DebugPrintEx(
  1845. DEBUG_ERR,
  1846. TEXT("SMTPPort invalid value read : %ld"),
  1847. dwRes);
  1848. goto exit;
  1849. }
  1850. pReceiptsConfig->bIsToUseForMSRouteThroughEmailMethod =
  1851. GetRegistryDword (hReceiptsKey, REGVAL_ISFOR_MSROUTE);
  1852. pReceiptsConfig->SMTPAuthOption =
  1853. (FAX_ENUM_SMTP_AUTH_OPTIONS)GetRegistryDword (hReceiptsKey, REGVAL_RECEIPTS_SMTP_AUTH_TYPE);
  1854. if ((FAX_SMTP_AUTH_ANONYMOUS > pReceiptsConfig->SMTPAuthOption) ||
  1855. (FAX_SMTP_AUTH_NTLM < pReceiptsConfig->SMTPAuthOption))
  1856. {
  1857. //
  1858. // Value out of range
  1859. //
  1860. dwRes = ERROR_BADDB;
  1861. SetLastError (dwRes);
  1862. DebugPrintEx(
  1863. DEBUG_ERR,
  1864. TEXT("SMTPAuthOption value out of range"));
  1865. goto exit;
  1866. }
  1867. pReceiptsConfig->dwAllowedReceipts =GetRegistryDword (hReceiptsKey, REGVAL_RECEIPTS_TYPE);
  1868. if (pReceiptsConfig->dwAllowedReceipts & ~DRT_ALL)
  1869. {
  1870. //
  1871. // Value out of range
  1872. //
  1873. dwRes = ERROR_BADDB;
  1874. SetLastError (dwRes);
  1875. DebugPrintEx(
  1876. DEBUG_ERR,
  1877. TEXT("AllowedReceipts value out of range"));
  1878. goto exit;
  1879. }
  1880. pReceiptsConfig->lptstrSMTPServer = GetRegistryString (hReceiptsKey, REGVAL_RECEIPTS_SERVER, EMPTY_STRING);
  1881. pReceiptsConfig->lptstrSMTPFrom = GetRegistryString (hReceiptsKey, REGVAL_RECEIPTS_FROM, EMPTY_STRING);
  1882. pReceiptsConfig->lptstrSMTPPassword = NULL; // we do not hold the password in memory - we read it only when we need to
  1883. pReceiptsConfig->lptstrSMTPUserName = GetRegistryString (hReceiptsKey, REGVAL_RECEIPTS_USER, EMPTY_STRING);
  1884. pReceiptsConfig->lptstrReserved = NULL;
  1885. if (TRUE == IsDesktopSKU())
  1886. {
  1887. //
  1888. // We do not support SMTP receipts on desktop SKUs
  1889. //
  1890. pReceiptsConfig->dwAllowedReceipts &= ~DRT_EMAIL;
  1891. }
  1892. Assert (ERROR_SUCCESS == dwRes);
  1893. exit:
  1894. if (NULL != hReceiptsKey)
  1895. {
  1896. RegCloseKey (hReceiptsKey);
  1897. }
  1898. return dwRes;
  1899. } // LoadReceiptsSettings
  1900. DWORD
  1901. StoreOutboxSettings (
  1902. PFAX_OUTBOX_CONFIG pOutboxCfg
  1903. )
  1904. /*++
  1905. Routine name : StoreOutboxSettings
  1906. Routine description:
  1907. Stores Outbox configuration to the registry.
  1908. Author:
  1909. Eran Yariv (EranY), Nov, 1999
  1910. Arguments:
  1911. pOutboxCfg [in] - Outbox configuration to write
  1912. Return Value:
  1913. Standard Win32 error code
  1914. --*/
  1915. {
  1916. DWORD dwRes = ERROR_SUCCESS;
  1917. HKEY hKey = NULL;
  1918. DEBUG_FUNCTION_NAME(TEXT("StoreOutboxSettings"));
  1919. hKey = OpenRegistryKey(
  1920. HKEY_LOCAL_MACHINE,
  1921. REGKEY_SOFTWARE,
  1922. FALSE,
  1923. KEY_WRITE );
  1924. if (NULL == hKey)
  1925. {
  1926. dwRes = GetLastError ();
  1927. DebugPrintEx(
  1928. DEBUG_ERR,
  1929. TEXT("Can't open key : %ld"),
  1930. dwRes);
  1931. return dwRes;
  1932. }
  1933. if (!SetRegistryDword( hKey, REGVAL_RETRIES, pOutboxCfg->dwRetries ))
  1934. {
  1935. dwRes = GetLastError ();
  1936. DebugPrintEx(
  1937. DEBUG_ERR,
  1938. TEXT("Can't SetRegistryDword(REGVAL_RETRIES) : %ld"),
  1939. dwRes);
  1940. goto exit;
  1941. }
  1942. if (!SetRegistryDword( hKey, REGVAL_RETRYDELAY, pOutboxCfg->dwRetryDelay ))
  1943. {
  1944. dwRes = GetLastError ();
  1945. DebugPrintEx(
  1946. DEBUG_ERR,
  1947. TEXT("Can't SetRegistryDword(REGVAL_RETRYDELAY) : %ld"),
  1948. dwRes);
  1949. goto exit;
  1950. }
  1951. if (!SetRegistryDword( hKey, REGVAL_DIRTYDAYS, pOutboxCfg->dwAgeLimit ))
  1952. {
  1953. dwRes = GetLastError ();
  1954. DebugPrintEx(
  1955. DEBUG_ERR,
  1956. TEXT("Can't SetRegistryDword(REGVAL_DIRTYDAYS) : %ld"),
  1957. dwRes);
  1958. goto exit;
  1959. }
  1960. if (!SetRegistryDword( hKey, REGVAL_BRANDING, pOutboxCfg->bBranding ))
  1961. {
  1962. dwRes = GetLastError ();
  1963. DebugPrintEx(
  1964. DEBUG_ERR,
  1965. TEXT("Can't SetRegistryDword(REGVAL_BRANDING) : %ld"),
  1966. dwRes);
  1967. goto exit;
  1968. }
  1969. if (!SetRegistryDword( hKey, REGVAL_USE_DEVICE_TSID, pOutboxCfg->bUseDeviceTSID ))
  1970. {
  1971. dwRes = GetLastError ();
  1972. DebugPrintEx(
  1973. DEBUG_ERR,
  1974. TEXT("Can't SetRegistryDword(REGVAL_USE_DEVICE_TSID) : %ld"),
  1975. dwRes);
  1976. goto exit;
  1977. }
  1978. if (!SetRegistryDword( hKey, REGVAL_SERVERCP, !pOutboxCfg->bAllowPersonalCP ))
  1979. {
  1980. dwRes = GetLastError ();
  1981. DebugPrintEx(
  1982. DEBUG_ERR,
  1983. TEXT("Can't SetRegistryDword(REGVAL_SERVERCP) : %ld"),
  1984. dwRes);
  1985. goto exit;
  1986. }
  1987. if (!SetRegistryDword( hKey,
  1988. REGVAL_STARTCHEAP,
  1989. MAKELONG(pOutboxCfg->dtDiscountStart.Hour,
  1990. pOutboxCfg->dtDiscountStart.Minute) ))
  1991. {
  1992. dwRes = GetLastError ();
  1993. DebugPrintEx(
  1994. DEBUG_ERR,
  1995. TEXT("Can't SetRegistryDword(REGVAL_STARTCHEAP) : %ld"),
  1996. dwRes);
  1997. goto exit;
  1998. }
  1999. if (!SetRegistryDword( hKey,
  2000. REGVAL_STOPCHEAP,
  2001. MAKELONG(pOutboxCfg->dtDiscountEnd.Hour,
  2002. pOutboxCfg->dtDiscountEnd.Minute) ))
  2003. {
  2004. dwRes = GetLastError ();
  2005. DebugPrintEx(
  2006. DEBUG_ERR,
  2007. TEXT("Can't SetRegistryDword(REGVAL_STOPCHEAP) : %ld"),
  2008. dwRes);
  2009. goto exit;
  2010. }
  2011. Assert (ERROR_SUCCESS == dwRes);
  2012. exit:
  2013. if (NULL != hKey)
  2014. {
  2015. RegCloseKey (hKey);
  2016. }
  2017. return dwRes;
  2018. } // StoreOutboxSettings
  2019. DWORD
  2020. LoadArchiveSettings (
  2021. FAX_ENUM_MESSAGE_FOLDER Folder,
  2022. PFAX_ARCHIVE_CONFIG pCfg
  2023. )
  2024. /*++
  2025. Routine name : LoadArchiveSettings
  2026. Routine description:
  2027. Reads archive configuration from the registry.
  2028. Ovverride destination strings without freeing anything.
  2029. Author:
  2030. Eran Yariv (EranY), Nov, 1999
  2031. Arguments:
  2032. Folder [in ] - Archive folder type
  2033. pCfg [out] - Archive configuration to read
  2034. Return Value:
  2035. Standard Win32 error code
  2036. --*/
  2037. {
  2038. DWORD dwRes = ERROR_SUCCESS;
  2039. HKEY hKey = NULL;
  2040. DEBUG_FUNCTION_NAME(TEXT("LoadArchiveSettings"));
  2041. Assert (FAX_MESSAGE_FOLDER_INBOX == Folder ||
  2042. FAX_MESSAGE_FOLDER_SENTITEMS == Folder);
  2043. Assert (pCfg);
  2044. hKey = OpenRegistryKey(
  2045. HKEY_LOCAL_MACHINE,
  2046. FAX_MESSAGE_FOLDER_INBOX == Folder ?
  2047. REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_INBOX_CONFIG :
  2048. REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG,
  2049. FALSE,
  2050. KEY_READ | KEY_WRITE );
  2051. if (NULL == hKey)
  2052. {
  2053. dwRes = GetLastError ();
  2054. DebugPrintEx(
  2055. DEBUG_ERR,
  2056. TEXT("Can't open key : %ld"),
  2057. dwRes);
  2058. return dwRes;
  2059. }
  2060. pCfg->dwSizeOfStruct = sizeof (FAX_ARCHIVE_CONFIG);
  2061. pCfg->bUseArchive = GetRegistryDword (hKey, REGVAL_ARCHIVE_USE);
  2062. pCfg->bSizeQuotaWarning = GetRegistryDword (hKey, REGVAL_ARCHIVE_SIZE_QUOTA_WARNING);
  2063. pCfg->dwSizeQuotaHighWatermark = GetRegistryDword (hKey, REGVAL_ARCHIVE_HIGH_WATERMARK);
  2064. pCfg->dwSizeQuotaLowWatermark = GetRegistryDword (hKey, REGVAL_ARCHIVE_LOW_WATERMARK);
  2065. pCfg->dwAgeLimit = GetRegistryDword (hKey, REGVAL_ARCHIVE_AGE_LIMIT);
  2066. if (pCfg->bUseArchive &&
  2067. (pCfg->dwSizeQuotaHighWatermark < pCfg->dwSizeQuotaLowWatermark))
  2068. {
  2069. //
  2070. // Invalid value
  2071. //
  2072. DebugPrintEx(DEBUG_ERR, TEXT("Invalid archive watermarks"));
  2073. dwRes = ERROR_INVALID_DATA;
  2074. goto exit;
  2075. }
  2076. pCfg->lpcstrFolder = GetRegistryString (hKey, REGVAL_ARCHIVE_FOLDER, BAD_FOLDER_STRING);
  2077. if (pCfg->bUseArchive && !lstrcmp (BAD_FOLDER_STRING, pCfg->lpcstrFolder))
  2078. {
  2079. //
  2080. // Invalid value
  2081. //
  2082. DebugPrintEx(DEBUG_ERR, TEXT("Invalid archive folder"));
  2083. dwRes = ERROR_INVALID_DATA;
  2084. MemFree (pCfg->lpcstrFolder);
  2085. pCfg->lpcstrFolder = NULL;
  2086. goto exit;
  2087. }
  2088. Assert (ERROR_SUCCESS == dwRes);
  2089. exit:
  2090. if (NULL != hKey)
  2091. {
  2092. RegCloseKey (hKey);
  2093. }
  2094. return dwRes;
  2095. } // LoadArchiveSettings
  2096. DWORD
  2097. StoreArchiveSettings (
  2098. FAX_ENUM_MESSAGE_FOLDER Folder,
  2099. PFAX_ARCHIVE_CONFIG pCfg
  2100. )
  2101. /*++
  2102. Routine name : StoreArchiveSettings
  2103. Routine description:
  2104. Writes archive configuration to the registry.
  2105. Author:
  2106. Eran Yariv (EranY), Nov, 1999
  2107. Arguments:
  2108. Folder [in] - Archive folder type
  2109. pCfg [in] - Archive configuration to write
  2110. Return Value:
  2111. Standard Win32 error code
  2112. --*/
  2113. {
  2114. DWORD dwRes = ERROR_SUCCESS;
  2115. HKEY hServerKey = NULL;
  2116. HKEY hKey = NULL;
  2117. DEBUG_FUNCTION_NAME(TEXT("StoreArchiveSettings"));
  2118. Assert (FAX_MESSAGE_FOLDER_INBOX == Folder ||
  2119. FAX_MESSAGE_FOLDER_SENTITEMS == Folder);
  2120. Assert (pCfg);
  2121. hServerKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_WRITE );
  2122. if (NULL == hServerKey)
  2123. {
  2124. dwRes = GetLastError ();
  2125. DebugPrintEx(
  2126. DEBUG_ERR,
  2127. TEXT("Can't open key : %ld"),
  2128. dwRes);
  2129. return dwRes;
  2130. }
  2131. dwRes = RegCreateKey ( hServerKey,
  2132. FAX_MESSAGE_FOLDER_INBOX == Folder ?
  2133. REGKEY_ARCHIVE_INBOX_CONFIG :
  2134. REGKEY_ARCHIVE_SENTITEMS_CONFIG,
  2135. &hKey);
  2136. if (ERROR_SUCCESS != dwRes)
  2137. {
  2138. DebugPrintEx(
  2139. DEBUG_ERR,
  2140. TEXT("Can't create or open key : %ld"),
  2141. dwRes);
  2142. goto exit;
  2143. }
  2144. if (!SetRegistryDword( hKey, REGVAL_ARCHIVE_USE, pCfg->bUseArchive))
  2145. {
  2146. dwRes = GetLastError ();
  2147. DebugPrintEx(
  2148. DEBUG_ERR,
  2149. TEXT("Can't write value : %ld"),
  2150. dwRes);
  2151. goto exit;
  2152. }
  2153. if (!SetRegistryDword( hKey, REGVAL_ARCHIVE_SIZE_QUOTA_WARNING, pCfg->bSizeQuotaWarning))
  2154. {
  2155. dwRes = GetLastError ();
  2156. DebugPrintEx(
  2157. DEBUG_ERR,
  2158. TEXT("Can't write value : %ld"),
  2159. dwRes);
  2160. goto exit;
  2161. }
  2162. if (!SetRegistryDword( hKey, REGVAL_ARCHIVE_HIGH_WATERMARK, pCfg->dwSizeQuotaHighWatermark))
  2163. {
  2164. dwRes = GetLastError ();
  2165. DebugPrintEx(
  2166. DEBUG_ERR,
  2167. TEXT("Can't write value : %ld"),
  2168. dwRes);
  2169. goto exit;
  2170. }
  2171. if (!SetRegistryDword( hKey, REGVAL_ARCHIVE_LOW_WATERMARK, pCfg->dwSizeQuotaLowWatermark))
  2172. {
  2173. dwRes = GetLastError ();
  2174. DebugPrintEx(
  2175. DEBUG_ERR,
  2176. TEXT("Can't write value : %ld"),
  2177. dwRes);
  2178. goto exit;
  2179. }
  2180. if (!SetRegistryDword( hKey, REGVAL_ARCHIVE_AGE_LIMIT, pCfg->dwAgeLimit))
  2181. {
  2182. dwRes = GetLastError ();
  2183. DebugPrintEx(
  2184. DEBUG_ERR,
  2185. TEXT("Can't write value : %ld"),
  2186. dwRes);
  2187. goto exit;
  2188. }
  2189. if (!SetRegistryString( hKey,
  2190. REGVAL_ARCHIVE_FOLDER,
  2191. pCfg->lpcstrFolder ? pCfg->lpcstrFolder : EMPTY_STRING))
  2192. {
  2193. dwRes = GetLastError ();
  2194. DebugPrintEx(
  2195. DEBUG_ERR,
  2196. TEXT("Can't write value : %ld"),
  2197. dwRes);
  2198. goto exit;
  2199. }
  2200. Assert (ERROR_SUCCESS == dwRes);
  2201. exit:
  2202. if (NULL != hKey)
  2203. {
  2204. RegCloseKey (hKey);
  2205. }
  2206. if (NULL != hServerKey)
  2207. {
  2208. RegCloseKey (hServerKey);
  2209. }
  2210. return dwRes;
  2211. } // StoreArchiveSettings
  2212. DWORD
  2213. LoadActivityLoggingSettings (
  2214. PFAX_SERVER_ACTIVITY_LOGGING_CONFIG pLogCfg
  2215. )
  2216. /*++
  2217. Routine name : LoadActivityLoggingSettings
  2218. Routine description:
  2219. Reads activity logging configuration from the registry.
  2220. Author:
  2221. Eran Yariv (EranY), Nov, 1999
  2222. Arguments:
  2223. pLogCfg [in] - Activity logging configuration to read
  2224. Return Value:
  2225. Standard Win32 error code
  2226. --*/
  2227. {
  2228. DWORD dwRes = ERROR_SUCCESS;
  2229. HKEY hKey = NULL;
  2230. DEBUG_FUNCTION_NAME(TEXT("LoadActivityLoggingSettings"));
  2231. Assert (pLogCfg);
  2232. hKey = OpenRegistryKey(
  2233. HKEY_LOCAL_MACHINE,
  2234. REGKEY_SOFTWARE TEXT("\\") REGKEY_ACTIVITY_LOG_CONFIG,
  2235. FALSE,
  2236. KEY_READ | KEY_WRITE );
  2237. if (NULL == hKey)
  2238. {
  2239. dwRes = GetLastError ();
  2240. DebugPrintEx(
  2241. DEBUG_ERR,
  2242. TEXT("Can't open key : %ld"),
  2243. dwRes);
  2244. return dwRes;
  2245. }
  2246. pLogCfg->dwSizeOfStruct = sizeof (FAX_ACTIVITY_LOGGING_CONFIG);
  2247. pLogCfg->bLogIncoming = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_IN);
  2248. pLogCfg->bLogOutgoing = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_OUT);
  2249. //
  2250. // read Activity log file limit criterions setting
  2251. //
  2252. // Notice: This settings are not configurable through UI nor RPC calls.
  2253. // The only way to configure them is through directly registry settings.
  2254. // Hence StoreActivityLoggingSettings() will not persist this settings back to the registry
  2255. //
  2256. pLogCfg->dwLogLimitCriteria = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_LIMIT_CRITERIA);
  2257. pLogCfg->dwLogSizeLimit = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_SIZE_LIMIT);
  2258. pLogCfg->dwLogAgeLimit = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_AGE_LIMIT);
  2259. pLogCfg->dwLimitReachedAction = GetRegistryDword (hKey, REGVAL_ACTIVITY_LOG_LIMIT_REACHED_ACTION);
  2260. if ( 0 == pLogCfg->dwLogSizeLimit)
  2261. {
  2262. //
  2263. // Illegal value, set default value
  2264. //
  2265. DebugPrintEx(
  2266. DEBUG_ERR,
  2267. TEXT("Illegal value in dwLogSizeLimit. Default value of %ld Mbytes is used."),
  2268. ACTIVITY_LOG_DEFAULT_SIZE_LIMIT);
  2269. pLogCfg->dwLogSizeLimit = ACTIVITY_LOG_DEFAULT_SIZE_LIMIT;
  2270. }
  2271. if ( 0 == pLogCfg->dwLogAgeLimit )
  2272. {
  2273. //
  2274. // Illegal value, set default value
  2275. //
  2276. DebugPrintEx(
  2277. DEBUG_ERR,
  2278. TEXT("Illegal value in dwLogAgeLimit. Default value of %ld months is used."),
  2279. ACTIVITY_LOG_DEFAULT_AGE_LIMIT);
  2280. pLogCfg->dwLogAgeLimit = ACTIVITY_LOG_DEFAULT_AGE_LIMIT;
  2281. }
  2282. if ( ACTIVITY_LOG_LIMIT_CRITERIA_NONE != pLogCfg->dwLogLimitCriteria &&
  2283. ACTIVITY_LOG_LIMIT_CRITERIA_SIZE != pLogCfg->dwLogLimitCriteria &&
  2284. ACTIVITY_LOG_LIMIT_CRITERIA_AGE != pLogCfg->dwLogLimitCriteria )
  2285. {
  2286. //
  2287. // Illegal value, set default value
  2288. //
  2289. DebugPrintEx(
  2290. DEBUG_ERR,
  2291. TEXT("Illegal value in dwLogLimitCriteria. Default value (not using logging limit) - is used.")
  2292. );
  2293. pLogCfg->dwLogLimitCriteria = ACTIVITY_LOG_LIMIT_CRITERIA_NONE;
  2294. }
  2295. if ( ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY != pLogCfg->dwLimitReachedAction &&
  2296. ACTIVITY_LOG_LIMIT_REACHED_ACTION_DELETE != pLogCfg->dwLimitReachedAction )
  2297. {
  2298. //
  2299. // Illegal value, set default value
  2300. //
  2301. DebugPrintEx(
  2302. DEBUG_ERR,
  2303. TEXT("Illegal value in dwLogLimitCriteria. Default value (copy log file) is used.")
  2304. );
  2305. pLogCfg->dwLimitReachedAction = ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY;
  2306. }
  2307. if (pLogCfg->bLogIncoming || pLogCfg->bLogOutgoing)
  2308. {
  2309. pLogCfg->lptstrDBPath = GetRegistryString (hKey, REGVAL_ACTIVITY_LOG_DB, BAD_FOLDER_STRING);
  2310. }
  2311. else
  2312. {
  2313. //
  2314. // No logging => DB path is NULL
  2315. //
  2316. pLogCfg->lptstrDBPath = NULL;
  2317. }
  2318. if ((pLogCfg->bLogIncoming || pLogCfg->bLogOutgoing) &&
  2319. !lstrcmp (BAD_FOLDER_STRING, pLogCfg->lptstrDBPath))
  2320. {
  2321. //
  2322. // Invalid value
  2323. //
  2324. DebugPrintEx(DEBUG_ERR, TEXT("Invalid activity logging database"));
  2325. dwRes = ERROR_INVALID_DATA;
  2326. MemFree (pLogCfg->lptstrDBPath);
  2327. pLogCfg->lptstrDBPath = NULL;
  2328. goto exit;
  2329. }
  2330. Assert (ERROR_SUCCESS == dwRes);
  2331. exit:
  2332. if (NULL != hKey)
  2333. {
  2334. RegCloseKey (hKey);
  2335. }
  2336. return dwRes;
  2337. } // LoadActivityLoggingSettings
  2338. DWORD
  2339. StoreActivityLoggingSettings (
  2340. PFAX_ACTIVITY_LOGGING_CONFIG pLogCfg
  2341. )
  2342. /*++
  2343. Routine name : StoreActivityLoggingSettings
  2344. Routine description:
  2345. Writes activity logging configuration to the registry.
  2346. Author:
  2347. Eran Yariv (EranY), Nov, 1999
  2348. Arguments:
  2349. pLogCfg [in] - Activity logging configuration to write
  2350. Return Value:
  2351. Standard Win32 error code
  2352. --*/
  2353. {
  2354. DWORD dwRes = ERROR_SUCCESS;
  2355. HKEY hServerKey = NULL;
  2356. HKEY hKey = NULL;
  2357. DEBUG_FUNCTION_NAME(TEXT("StoreActivityLoggingSettings"));
  2358. Assert (pLogCfg);
  2359. hServerKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_WRITE );
  2360. if (NULL == hServerKey)
  2361. {
  2362. dwRes = GetLastError ();
  2363. DebugPrintEx(
  2364. DEBUG_ERR,
  2365. TEXT("Can't open key : %ld"),
  2366. dwRes);
  2367. return dwRes;
  2368. }
  2369. dwRes = RegCreateKey ( hServerKey,
  2370. REGKEY_ACTIVITY_LOG_CONFIG,
  2371. &hKey);
  2372. if (ERROR_SUCCESS != dwRes)
  2373. {
  2374. DebugPrintEx(
  2375. DEBUG_ERR,
  2376. TEXT("Can't create or open key : %ld"),
  2377. dwRes);
  2378. goto exit;
  2379. }
  2380. if (!SetRegistryDword( hKey, REGVAL_ACTIVITY_LOG_IN, pLogCfg->bLogIncoming))
  2381. {
  2382. dwRes = GetLastError ();
  2383. DebugPrintEx(
  2384. DEBUG_ERR,
  2385. TEXT("Can't write value : %ld"),
  2386. dwRes);
  2387. goto exit;
  2388. }
  2389. if (!SetRegistryDword( hKey, REGVAL_ACTIVITY_LOG_OUT, pLogCfg->bLogOutgoing))
  2390. {
  2391. dwRes = GetLastError ();
  2392. DebugPrintEx(
  2393. DEBUG_ERR,
  2394. TEXT("Can't write value : %ld"),
  2395. dwRes);
  2396. goto exit;
  2397. }
  2398. if (!SetRegistryString( hKey,
  2399. REGVAL_ACTIVITY_LOG_DB,
  2400. pLogCfg->lptstrDBPath ? pLogCfg->lptstrDBPath : EMPTY_STRING))
  2401. {
  2402. dwRes = GetLastError ();
  2403. DebugPrintEx(
  2404. DEBUG_ERR,
  2405. TEXT("Can't write value : %ld"),
  2406. dwRes);
  2407. goto exit;
  2408. }
  2409. Assert (ERROR_SUCCESS == dwRes);
  2410. exit:
  2411. if (NULL != hKey)
  2412. {
  2413. RegCloseKey (hKey);
  2414. }
  2415. if (NULL != hServerKey)
  2416. {
  2417. RegCloseKey (hServerKey);
  2418. }
  2419. return dwRes;
  2420. } // StoreActivityLoggingSettings
  2421. DWORD
  2422. StoreDeviceConfig (
  2423. DWORD dwDeviceId,
  2424. PFAX_PORT_INFO_EX pPortInfo,
  2425. BOOL bVirtualDevice
  2426. )
  2427. /*++
  2428. Routine name : StoreDeviceConfig
  2429. Routine description:
  2430. Writes device configuration to the registry.
  2431. Author:
  2432. Eran Yariv (EranY), Nov, 1999
  2433. Arguments:
  2434. dwDeviceId [in] - Device identifier
  2435. pPortInfo [in] - Configuration bloack to write.
  2436. Writes: Enable send flag
  2437. Enable receive flag
  2438. Rings for answer count
  2439. CSID
  2440. TSID
  2441. Description
  2442. bVirtualDevice [in] - Should we set FPF_VIRTUAL ?
  2443. Return Value:
  2444. Standard Win32 error code
  2445. --*/
  2446. {
  2447. DWORD dwRes = ERROR_SUCCESS;
  2448. HKEY hKey = NULL;
  2449. TCHAR wszSubKeyName[MAX_PATH];
  2450. DWORD dwFlags = 0;
  2451. DEBUG_FUNCTION_NAME(TEXT("StoreDeviceConfig"));
  2452. Assert (pPortInfo);
  2453. _stprintf( wszSubKeyName, TEXT("%s\\%010d\\%s"), REGKEY_FAX_DEVICES, dwDeviceId, REGKEY_FAXSVC_DEVICE_GUID );
  2454. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, wszSubKeyName, FALSE, KEY_WRITE );
  2455. if (NULL == hKey)
  2456. {
  2457. dwRes = GetLastError ();
  2458. DebugPrintEx(
  2459. DEBUG_ERR,
  2460. TEXT("Can't open device key : %ld"),
  2461. dwRes);
  2462. ASSERT_FALSE; // The device must exist !!!
  2463. return dwRes;
  2464. }
  2465. if (bVirtualDevice)
  2466. {
  2467. dwFlags |= FPF_VIRTUAL;
  2468. }
  2469. if (FAX_DEVICE_RECEIVE_MODE_AUTO == pPortInfo->ReceiveMode)
  2470. {
  2471. dwFlags |= FPF_RECEIVE;
  2472. }
  2473. if (pPortInfo->bSend)
  2474. {
  2475. dwFlags |= FPF_SEND;
  2476. }
  2477. if (!SetRegistryDword( hKey, REGVAL_FLAGS, dwFlags))
  2478. {
  2479. dwRes = GetLastError ();
  2480. DebugPrintEx(
  2481. DEBUG_ERR,
  2482. TEXT("Can't write value : %ld"),
  2483. dwRes);
  2484. goto exit;
  2485. }
  2486. if (!SetRegistryDword( hKey, REGVAL_RINGS, pPortInfo->dwRings))
  2487. {
  2488. dwRes = GetLastError ();
  2489. DebugPrintEx(
  2490. DEBUG_ERR,
  2491. TEXT("Can't write value : %ld"),
  2492. dwRes);
  2493. goto exit;
  2494. }
  2495. if (!SetRegistryString( hKey, REGVAL_ROUTING_CSID, pPortInfo->lptstrCsid))
  2496. {
  2497. dwRes = GetLastError ();
  2498. DebugPrintEx(
  2499. DEBUG_ERR,
  2500. TEXT("Can't write value : %ld"),
  2501. dwRes);
  2502. goto exit;
  2503. }
  2504. if (!SetRegistryString( hKey, REGVAL_ROUTING_TSID, pPortInfo->lptstrTsid))
  2505. {
  2506. dwRes = GetLastError ();
  2507. DebugPrintEx(
  2508. DEBUG_ERR,
  2509. TEXT("Can't write value : %ld"),
  2510. dwRes);
  2511. goto exit;
  2512. }
  2513. if (!SetRegistryString( hKey, REGVAL_DEVICE_DESCRIPTION, pPortInfo->lptstrDescription))
  2514. {
  2515. dwRes = GetLastError ();
  2516. DebugPrintEx(
  2517. DEBUG_ERR,
  2518. TEXT("Can't write value : %ld"),
  2519. dwRes);
  2520. goto exit;
  2521. }
  2522. Assert (ERROR_SUCCESS == dwRes);
  2523. exit:
  2524. if (NULL != hKey)
  2525. {
  2526. RegCloseKey (hKey);
  2527. }
  2528. return dwRes;
  2529. } // StoreDeviceConfig
  2530. static
  2531. DWORD
  2532. OpenExtensionKey (
  2533. DWORD dwDeviceId,
  2534. FAX_ENUM_DEVICE_ID_SOURCE DevIdSrc,
  2535. PHKEY lphKey
  2536. )
  2537. /*++
  2538. Routine name : OpenExtensionKey
  2539. Routine description:
  2540. Opens the extension's configuration key according to the device id
  2541. Author:
  2542. Eran Yariv (EranY), Nov, 1999
  2543. Arguments:
  2544. dwDeviceId [in ] - Device identifier
  2545. DevIdSrc [in ] - Class of device id (Fax / TAPI)
  2546. lphKey [out] - Registry handle to open key
  2547. Return Value:
  2548. Standard Win32 error code
  2549. --*/
  2550. {
  2551. DWORD dwRes = ERROR_SUCCESS;
  2552. TCHAR wszSubKeyName[MAX_PATH];
  2553. DEBUG_FUNCTION_NAME(TEXT("OpenExtensionKey"));
  2554. Assert (lphKey);
  2555. if (0 == dwDeviceId)
  2556. {
  2557. //
  2558. // Non-associated data is always written under the fax devices key
  2559. //
  2560. DevIdSrc = DEV_ID_SRC_FAX;
  2561. }
  2562. switch (DevIdSrc)
  2563. {
  2564. case DEV_ID_SRC_FAX:
  2565. if (!dwDeviceId)
  2566. {
  2567. //
  2568. // We're dealing with an unassociated device here
  2569. //
  2570. _stprintf( wszSubKeyName,
  2571. TEXT("%s\\%s"),
  2572. REGKEY_FAX_DEVICES,
  2573. REGKEY_UNASSOC_EXTENSION_DATA );
  2574. }
  2575. else
  2576. {
  2577. //
  2578. // Extension data associated with a device , saved under service GUID !!!
  2579. //
  2580. _stprintf( wszSubKeyName, TEXT("%s\\%010d\\%s"), REGKEY_FAX_DEVICES, dwDeviceId, REGKEY_FAXSVC_DEVICE_GUID );
  2581. }
  2582. break;
  2583. case DEV_ID_SRC_TAPI:
  2584. Assert (dwDeviceId);
  2585. {
  2586. //
  2587. // Make sure the key of TAPI devices configuration exists - create if needed.
  2588. //
  2589. HKEY hkeyTAPIConfig = OpenRegistryKey (HKEY_LOCAL_MACHINE,
  2590. REGKEY_TAPIDEVICES,
  2591. TRUE,
  2592. KEY_READ);
  2593. if (NULL == hkeyTAPIConfig)
  2594. {
  2595. dwRes = GetLastError ();
  2596. DebugPrintEx(
  2597. DEBUG_ERR,
  2598. TEXT("Can't open / create TAPI devices configuration key : %ld"),
  2599. dwRes);
  2600. return dwRes;
  2601. }
  2602. RegCloseKey (hkeyTAPIConfig);
  2603. }
  2604. _stprintf( wszSubKeyName, TEXT("%s\\%08lx"), REGKEY_TAPIDEVICES, dwDeviceId );
  2605. break;
  2606. default:
  2607. ASSERT_FALSE;
  2608. return ERROR_GEN_FAILURE;
  2609. }
  2610. //
  2611. // Try to open device key (create if needed)
  2612. //
  2613. *lphKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, wszSubKeyName, TRUE, KEY_READ | KEY_WRITE );
  2614. if (NULL == *lphKey)
  2615. {
  2616. dwRes = GetLastError ();
  2617. DebugPrintEx(
  2618. DEBUG_ERR,
  2619. TEXT("Can't open device (%ld) key : %ld"),
  2620. dwDeviceId,
  2621. dwRes);
  2622. }
  2623. return dwRes;
  2624. } // OpenExtensionKey
  2625. DWORD
  2626. ReadExtensionData (
  2627. DWORD dwDeviceId,
  2628. FAX_ENUM_DEVICE_ID_SOURCE DevIdSrc,
  2629. LPCWSTR lpcwstrNameGUID,
  2630. LPBYTE *ppData,
  2631. LPDWORD lpdwDataSize
  2632. )
  2633. /*++
  2634. Routine name : ReadExtensionData
  2635. Routine description:
  2636. Reads extesnion configuration data from the registry
  2637. Author:
  2638. Eran Yariv (EranY), Nov, 1999
  2639. Arguments:
  2640. dwDeviceId [in ] - Device identifier
  2641. 0 = Data is not associated with any given device
  2642. DevIdSrc [in ] - Class of device id (Fax / TAPI)
  2643. lpcwstrNameGUID [in ] - Name of data (GUID format)
  2644. ppData [out] - Pointer to block that receives the data.
  2645. lpdwDataSize [out] - Points to data size
  2646. Return Value:
  2647. Standard Win32 error code
  2648. --*/
  2649. {
  2650. DWORD dwRes = ERROR_SUCCESS;
  2651. HKEY hKey = NULL;
  2652. DEBUG_FUNCTION_NAME(TEXT("ReadExtensionData"));
  2653. Assert (ppData);
  2654. Assert (lpdwDataSize);
  2655. dwRes = OpenExtensionKey (dwDeviceId, DevIdSrc, &hKey);
  2656. if (ERROR_SUCCESS != dwRes)
  2657. {
  2658. return dwRes;
  2659. }
  2660. dwRes = GetRegistrySecureBinary(hKey,
  2661. lpcwstrNameGUID,
  2662. ppData,
  2663. lpdwDataSize,
  2664. TRUE, // Optionally non-ecrypted
  2665. NULL // Dont care if the data was decrypted or not
  2666. );
  2667. if (ERROR_SUCCESS != dwRes)
  2668. {
  2669. DebugPrintEx(
  2670. DEBUG_ERR,
  2671. TEXT("GetRegistrySecureBinary on device %ld and GUID %s failed with %ld"),
  2672. dwDeviceId,
  2673. lpcwstrNameGUID,
  2674. dwRes);
  2675. goto exit;
  2676. }
  2677. //
  2678. // Success
  2679. //
  2680. Assert (ERROR_SUCCESS == dwRes);
  2681. exit:
  2682. if (hKey)
  2683. {
  2684. RegCloseKey (hKey);
  2685. }
  2686. return dwRes;
  2687. } // ReadExtensionData
  2688. DWORD
  2689. WriteExtensionData (
  2690. DWORD dwDeviceId,
  2691. FAX_ENUM_DEVICE_ID_SOURCE DevIdSrc,
  2692. LPCWSTR lpcwstrNameGUID,
  2693. LPBYTE pData,
  2694. DWORD dwDataSize
  2695. )
  2696. /*++
  2697. Routine name : WriteExtensionData
  2698. Routine description:
  2699. Writes extesnion configuration data to the registry
  2700. Author:
  2701. Eran Yariv (EranY), Nov, 1999
  2702. Arguments:
  2703. dwDeviceId [in ] - Device identifier
  2704. 0 = Data is not associated with any given device
  2705. DevIdSrc [in ] - Class of device id (Fax / TAPI)
  2706. lpcwstrNameGUID [in ] - Name of data (GUID format)
  2707. pData [out] - Pointer to data.
  2708. dwDataSize [out] - Data size
  2709. Return Value:
  2710. Standard Win32 error code
  2711. --*/
  2712. {
  2713. DWORD dwRes = ERROR_SUCCESS;
  2714. HKEY hKey = NULL;
  2715. DEBUG_FUNCTION_NAME(TEXT("WriteExtensionData"));
  2716. Assert (pData);
  2717. Assert (dwDataSize);
  2718. dwRes = OpenExtensionKey (dwDeviceId, DevIdSrc, &hKey);
  2719. if (ERROR_SUCCESS != dwRes)
  2720. {
  2721. return dwRes;
  2722. }
  2723. //
  2724. // Write data
  2725. //
  2726. if (!SetRegistrySecureBinary (hKey,
  2727. lpcwstrNameGUID,
  2728. pData,
  2729. dwDataSize,
  2730. TRUE // Optionally non-ecrypted
  2731. ))
  2732. {
  2733. dwRes = GetLastError ();
  2734. DebugPrintEx(
  2735. DEBUG_ERR,
  2736. TEXT("SetRegistrySecureBinary on device %ld and GUID %s failed with %ld"),
  2737. dwDeviceId,
  2738. lpcwstrNameGUID,
  2739. dwRes);
  2740. }
  2741. RegCloseKey (hKey);
  2742. return dwRes;
  2743. } // WriteExtensionData
  2744. //********************************************
  2745. //* Outbound routing
  2746. //********************************************
  2747. HKEY
  2748. OpenOutboundGroupKey (
  2749. LPCWSTR lpcwstrGroupName,
  2750. BOOL fNewKey,
  2751. REGSAM SamDesired
  2752. )
  2753. /*++
  2754. Routine name : OpenOutboundGroupKey
  2755. Routine description:
  2756. Opens an outbound routing group key
  2757. Author:
  2758. Oded Sacher (OdedS), Dec, 1999
  2759. Arguments:
  2760. lpcwstrGroupName [in] - The outbound routing group name
  2761. fNewKey [in] - Flag that indicates to create a new key
  2762. SamDesired [in] - Desired access (See OpenRegistryKey)
  2763. Return Value:
  2764. Handle to the opened key. If this is NULL call GetLastError() for more info.
  2765. --*/
  2766. {
  2767. HKEY hGroupkey = NULL;
  2768. DEBUG_FUNCTION_NAME(TEXT("OpenOutboundGroupKey"));
  2769. WCHAR wszSubKeyName[2*MAX_PATH] = {0};
  2770. int Count;
  2771. Assert (lpcwstrGroupName);
  2772. Count = _snwprintf ( wszSubKeyName,
  2773. ARR_SIZE(wszSubKeyName) - 1,
  2774. TEXT("%s\\%s"),
  2775. REGKEY_FAX_OUTBOUND_ROUTING_GROUPS,
  2776. lpcwstrGroupName );
  2777. if (Count < 0)
  2778. {
  2779. DebugPrintEx(DEBUG_ERR, TEXT("File Name exceded MAX_PATH"));
  2780. SetLastError (ERROR_BUFFER_OVERFLOW);
  2781. return NULL;
  2782. }
  2783. hGroupkey = OpenRegistryKey( HKEY_LOCAL_MACHINE, wszSubKeyName, fNewKey, SamDesired );
  2784. if (NULL == hGroupkey)
  2785. {
  2786. DebugPrintEx(
  2787. DEBUG_ERR,
  2788. TEXT("Can't create group key, OpenRegistryKey failed : %ld"),
  2789. GetLastError());
  2790. }
  2791. return hGroupkey;
  2792. } //OpenOutboundGroupKey
  2793. HKEY
  2794. OpenOutboundRuleKey (
  2795. DWORD dwCountryCode,
  2796. DWORD dwAreaCode,
  2797. BOOL fNewKey,
  2798. REGSAM SamDesired
  2799. )
  2800. /*++
  2801. Routine name : OpenOutboundRuleKey
  2802. Routine description:
  2803. Opens an outbound routing group key
  2804. Author:
  2805. Oded Sacher (OdedS), Dec, 1999
  2806. Arguments:
  2807. dwCountryCode [in] - The outbound routing rule country code
  2808. dwAreaCode [in] - The outbound routing rule area code
  2809. fNewKey [in] - Flag that indicates to create a new key
  2810. SamDesired [in] - Desired access (See OpenRegistryKey)
  2811. Return Value:
  2812. Handle to the opened key. If this is NULL call GetLastError() for more info.
  2813. --*/
  2814. {
  2815. HKEY hRulekey = NULL;
  2816. DEBUG_FUNCTION_NAME(TEXT("OpenOutboundRuleKey"));
  2817. WCHAR wszSubKeyName[2*MAX_PATH] = {0};
  2818. int Count;
  2819. Count = _snwprintf ( wszSubKeyName,
  2820. ARR_SIZE(wszSubKeyName) - 1,
  2821. TEXT("%s\\%ld:%ld"),
  2822. REGKEY_FAX_OUTBOUND_ROUTING_RULES,
  2823. dwCountryCode,
  2824. dwAreaCode );
  2825. if (Count < 0)
  2826. {
  2827. DebugPrintEx(DEBUG_ERR, TEXT("File Name exceded MAX_PATH"));
  2828. SetLastError (ERROR_BUFFER_OVERFLOW);
  2829. return NULL;
  2830. }
  2831. hRulekey = OpenRegistryKey( HKEY_LOCAL_MACHINE, wszSubKeyName, fNewKey, SamDesired );
  2832. if (NULL == hRulekey)
  2833. {
  2834. DebugPrintEx(
  2835. DEBUG_ERR,
  2836. TEXT("Can't create rule key, OpenRegistryKey failed : %ld"),
  2837. GetLastError());
  2838. }
  2839. return hRulekey;
  2840. } // OpenOutboundRuleKey
  2841. DWORD
  2842. DeleteOutboundRuleKey (DWORD dwCountryCode, DWORD dwAreaCode)
  2843. /*++
  2844. Routine name : DeleteOutboundRuleKey
  2845. Routine description:
  2846. Deletes an existing outbound routing rule key
  2847. Author:
  2848. Oded Sacher (OdedS), Dec, 1999
  2849. Arguments:
  2850. dwCountryCode [in ] - The rule's country code
  2851. dwAreaCode [in ] - The rule's area code
  2852. Return Value:
  2853. Standard Win32 error code
  2854. --*/
  2855. {
  2856. HKEY hRulekey = NULL;
  2857. DEBUG_FUNCTION_NAME(TEXT("DeleteOutboundRuleKey"));
  2858. WCHAR wszSubKeyName[MAX_PATH];
  2859. DWORD dwRes = ERROR_SUCCESS;
  2860. int iCount;
  2861. iCount = _snwprintf ( wszSubKeyName,
  2862. MAX_PATH - 1,
  2863. TEXT("%ld:%ld"),
  2864. dwCountryCode,
  2865. dwAreaCode );
  2866. if (iCount < 0)
  2867. {
  2868. DebugPrintEx(DEBUG_ERR, TEXT("File Name exceded MAX_PATH"));
  2869. return ERROR_BUFFER_OVERFLOW;
  2870. }
  2871. hRulekey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_OUTBOUND_ROUTING_RULES, FALSE, DELETE );
  2872. if (NULL == hRulekey)
  2873. {
  2874. dwRes = GetLastError();
  2875. DebugPrintEx(
  2876. DEBUG_ERR,
  2877. TEXT("Can't open rule key, OpenRegistryKey failed : %ld"),
  2878. dwRes);
  2879. return dwRes;
  2880. }
  2881. dwRes = RegDeleteKey (hRulekey, wszSubKeyName);
  2882. if (ERROR_SUCCESS != dwRes)
  2883. {
  2884. DebugPrintEx(
  2885. DEBUG_ERR,
  2886. TEXT("RegDeleteKey failed, error %ld"),
  2887. dwRes);
  2888. }
  2889. RegCloseKey (hRulekey);
  2890. return dwRes;
  2891. } // DeleteOutboundRuleKey
  2892. DWORD
  2893. AddNewProviderToRegistry (
  2894. LPCWSTR lpctstrGUID,
  2895. LPCWSTR lpctstrFriendlyName,
  2896. LPCWSTR lpctstrImageName,
  2897. LPCWSTR lpctstrTspName,
  2898. DWORD dwFSPIVersion
  2899. )
  2900. /*++
  2901. Routine name : AddNewProviderToRegistry
  2902. Routine description:
  2903. Adds a new FSP entry to the registry
  2904. Author:
  2905. Eran Yariv (EranY), Dec, 1999
  2906. Arguments:
  2907. lpctstrGUID [in] - GUID of FSP
  2908. lpctstrFriendlyName [in] - Friendly name of FSP
  2909. lpctstrImageName [in] - Image name of FSP. May contain environment variables
  2910. lpctstrTspName [in] - TSP name of FSP.
  2911. dwFSPIVersion [in] - FSP's API version.
  2912. Return Value:
  2913. Standard Win32 error code
  2914. --*/
  2915. {
  2916. HKEY hKey = NULL;
  2917. HKEY hProviderKey = NULL;
  2918. DWORD dwRes;
  2919. DWORD dw;
  2920. DEBUG_FUNCTION_NAME(TEXT("AddNewProviderToRegistry"));
  2921. //
  2922. // Open providers key
  2923. //
  2924. dwRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, REGKEY_DEVICE_PROVIDER_KEY, 0, KEY_WRITE, &hKey);
  2925. if (ERROR_SUCCESS != dwRes)
  2926. {
  2927. DebugPrintEx(
  2928. DEBUG_ERR,
  2929. TEXT("Error opening providers key (ec = %ld)"),
  2930. dwRes);
  2931. return dwRes;
  2932. }
  2933. //
  2934. // Create key for provider
  2935. //
  2936. dwRes = RegCreateKey (hKey, lpctstrGUID, &hProviderKey);
  2937. if (ERROR_SUCCESS != dwRes)
  2938. {
  2939. DebugPrintEx(
  2940. DEBUG_ERR,
  2941. TEXT("Error creating provider key (%s) (ec = %ld)"),
  2942. lpctstrFriendlyName,
  2943. dwRes);
  2944. goto exit;
  2945. }
  2946. //
  2947. // Write provider's data into the key
  2948. //
  2949. if (!SetRegistryString (hProviderKey, REGVAL_FRIENDLY_NAME, lpctstrFriendlyName))
  2950. {
  2951. dwRes = GetLastError ();
  2952. DebugPrintEx(
  2953. DEBUG_ERR,
  2954. TEXT("Error writing string value (ec = %ld)"),
  2955. dwRes);
  2956. goto exit;
  2957. }
  2958. if (!SetRegistryStringExpand (hProviderKey, REGVAL_IMAGE_NAME, lpctstrImageName))
  2959. {
  2960. dwRes = GetLastError ();
  2961. DebugPrintEx(
  2962. DEBUG_ERR,
  2963. TEXT("Error writing auto-expand string value (ec = %ld)"),
  2964. dwRes);
  2965. goto exit;
  2966. }
  2967. if (!SetRegistryString (hProviderKey, REGVAL_PROVIDER_NAME, lpctstrTspName))
  2968. {
  2969. dwRes = GetLastError ();
  2970. DebugPrintEx(
  2971. DEBUG_ERR,
  2972. TEXT("Error writing string value (ec = %ld)"),
  2973. dwRes);
  2974. goto exit;
  2975. }
  2976. if (!SetRegistryString (hProviderKey, REGVAL_PROVIDER_GUID, lpctstrGUID))
  2977. {
  2978. dwRes = GetLastError ();
  2979. DebugPrintEx(
  2980. DEBUG_ERR,
  2981. TEXT("Error writing string value (ec = %ld)"),
  2982. dwRes);
  2983. goto exit;
  2984. }
  2985. if (!SetRegistryDword (hProviderKey, REGVAL_PROVIDER_API_VERSION, dwFSPIVersion))
  2986. {
  2987. dwRes = GetLastError ();
  2988. DebugPrintEx(
  2989. DEBUG_ERR,
  2990. TEXT("Error writing DWORD value (ec = %ld)"),
  2991. dwRes);
  2992. goto exit;
  2993. }
  2994. DebugPrintEx(
  2995. DEBUG_MSG,
  2996. TEXT("Provider %s successfuly added."),
  2997. lpctstrFriendlyName);
  2998. Assert (ERROR_SUCCESS == dwRes);
  2999. exit:
  3000. if (ERROR_SUCCESS != dwRes && hKey)
  3001. {
  3002. //
  3003. // Try to remove half-cooked key
  3004. //
  3005. dw = RegDeleteKey (hKey, lpctstrGUID);
  3006. if (ERROR_SUCCESS != dw)
  3007. {
  3008. DebugPrintEx(
  3009. DEBUG_ERR,
  3010. TEXT("Error deleting provider's key (ec = %ld)"),
  3011. dw);
  3012. }
  3013. }
  3014. if (hKey)
  3015. {
  3016. dw = RegCloseKey (hKey);
  3017. if (ERROR_SUCCESS != dw)
  3018. {
  3019. DebugPrintEx(
  3020. DEBUG_ERR,
  3021. TEXT("Error closing providers key (ec = %ld)"),
  3022. dw);
  3023. }
  3024. }
  3025. if (hProviderKey)
  3026. {
  3027. dw = RegCloseKey (hProviderKey);
  3028. if (ERROR_SUCCESS != dw)
  3029. {
  3030. DebugPrintEx(
  3031. DEBUG_ERR,
  3032. TEXT("Error closing provider's key (ec = %ld)"),
  3033. dw);
  3034. }
  3035. }
  3036. return dwRes;
  3037. } // AddNewProviderToRegistry
  3038. DWORD
  3039. RemoveProviderFromRegistry (
  3040. LPCWSTR lpctstrGUID
  3041. )
  3042. /*++
  3043. Routine name : RemoveProviderFromRegistry
  3044. Routine description:
  3045. Removes an existing FSP entry from the registry
  3046. Author:
  3047. Eran Yariv (EranY), Dec, 1999
  3048. Arguments:
  3049. lpctstrGUID [in] - GUID of FSP
  3050. Return Value:
  3051. Standard Win32 error code
  3052. --*/
  3053. {
  3054. HKEY hKey = NULL;
  3055. DWORD dwRes;
  3056. DWORD dw;
  3057. DEBUG_FUNCTION_NAME(TEXT("RemoveProviderFromRegistry"));
  3058. dwRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, REGKEY_DEVICE_PROVIDER_KEY,0, DELETE, &hKey);
  3059. if (ERROR_SUCCESS != dwRes)
  3060. {
  3061. DebugPrintEx(
  3062. DEBUG_ERR,
  3063. TEXT("Error opening providers key (ec = %ld)"),
  3064. dwRes);
  3065. return dwRes;
  3066. }
  3067. dwRes = RegDeleteKey (hKey, lpctstrGUID);
  3068. if (ERROR_SUCCESS != dwRes)
  3069. {
  3070. DebugPrintEx(
  3071. DEBUG_ERR,
  3072. TEXT("Error deleting provider key ( %s ) (ec = %ld)"),
  3073. lpctstrGUID,
  3074. dwRes);
  3075. }
  3076. dw = RegCloseKey (hKey);
  3077. if (ERROR_SUCCESS != dw)
  3078. {
  3079. DebugPrintEx(
  3080. DEBUG_ERR,
  3081. TEXT("Error closing providers key (ec = %ld)"),
  3082. dw);
  3083. }
  3084. return dwRes;
  3085. } // RemoveProviderFromRegistry
  3086. DWORD
  3087. WriteManualAnswerDeviceId (
  3088. DWORD dwDeviceId
  3089. )
  3090. /*++
  3091. Routine name : WriteManualAnswerDeviceId
  3092. Routine description:
  3093. Write the manual-answer device id to the registry
  3094. Author:
  3095. Eran Yariv (EranY), Dec, 2000
  3096. Arguments:
  3097. dwDeviceId [in] - Device id (0 = None)
  3098. Return Value:
  3099. Standard Win32 error code
  3100. --*/
  3101. {
  3102. HKEY hKey = NULL;
  3103. DWORD dwRes = ERROR_SUCCESS;
  3104. DEBUG_FUNCTION_NAME(TEXT("WriteManualAnswerDeviceId"));
  3105. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_WRITE );
  3106. if (!hKey)
  3107. {
  3108. dwRes = GetLastError ();
  3109. DebugPrintEx(
  3110. DEBUG_ERR,
  3111. TEXT("Error opening server key (ec = %ld)"),
  3112. dwRes);
  3113. return dwRes;
  3114. }
  3115. if (!SetRegistryDword (hKey, REGVAL_MANUAL_ANSWER_DEVICE, dwDeviceId))
  3116. {
  3117. dwRes = GetLastError ();
  3118. DebugPrintEx(
  3119. DEBUG_ERR,
  3120. TEXT("Error setting registry value (ec = %ld)"),
  3121. dwRes);
  3122. }
  3123. dwRes = RegCloseKey (hKey);
  3124. if (ERROR_SUCCESS != dwRes)
  3125. {
  3126. DebugPrintEx(
  3127. DEBUG_ERR,
  3128. TEXT("Error closing providers key (ec = %ld)"),
  3129. dwRes);
  3130. }
  3131. return dwRes;
  3132. } // WriteManualAnswerDeviceId
  3133. DWORD
  3134. ReadManualAnswerDeviceId (
  3135. LPDWORD lpdwDeviceId
  3136. )
  3137. /*++
  3138. Routine name : ReadManualAnswerDeviceId
  3139. Routine description:
  3140. Read the manual-answer device id from the registry
  3141. Author:
  3142. Eran Yariv (EranY), Dec, 2000
  3143. Arguments:
  3144. lpdwDeviceId [out] - Device id (0 = None)
  3145. Return Value:
  3146. Standard Win32 error code
  3147. --*/
  3148. {
  3149. HKEY hKey = NULL;
  3150. DWORD dwRes = ERROR_SUCCESS;
  3151. DEBUG_FUNCTION_NAME(TEXT("ReadManualAnswerDeviceId"));
  3152. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ );
  3153. if (!hKey)
  3154. {
  3155. dwRes = GetLastError ();
  3156. DebugPrintEx(
  3157. DEBUG_ERR,
  3158. TEXT("Error opening server key (ec = %ld)"),
  3159. dwRes);
  3160. return dwRes;
  3161. }
  3162. *lpdwDeviceId = GetRegistryDword (hKey, REGVAL_MANUAL_ANSWER_DEVICE);
  3163. dwRes = RegCloseKey (hKey);
  3164. if (ERROR_SUCCESS != dwRes)
  3165. {
  3166. DebugPrintEx(
  3167. DEBUG_ERR,
  3168. TEXT("Error closing providers key (ec = %ld)"),
  3169. dwRes);
  3170. }
  3171. return dwRes;
  3172. } // ReadManualAnswerDeviceId
  3173. DWORD
  3174. FaxCopyRegSubkeys(
  3175. LPCTSTR strDestSubKeyName,
  3176. HKEY hKeySrcHive,
  3177. LPCTSTR strSrcSubKeyName
  3178. )
  3179. /*++
  3180. Routine name : FaxCopyRegSubkeys
  3181. Routine description:
  3182. Copy a content of one registry key into another
  3183. using shell function SHCopyKey
  3184. Caller must supply the source key handle *AND* a subkey whose subkeys and values are to be copied
  3185. Author:
  3186. Caliv Nir (t-nicali), Mar, 2002
  3187. Arguments:
  3188. strDestSubKeyName [in] - Destination registry key name
  3189. strSrcSubKeyName [in] - Source registry key name
  3190. hKeySrcHive [in] - Handle to the source key (for example, HKEY_LOCAL_MACHINE).
  3191. Return Value:
  3192. ERROR_SUCCESS - on succesful move
  3193. win32 error code on failure
  3194. --*/
  3195. {
  3196. DWORD dwRet = ERROR_SUCCESS;
  3197. HKEY hKeyDest = NULL;
  3198. DEBUG_FUNCTION_NAME(TEXT("FaxCopyRegSubkeys"));
  3199. //
  3200. // Create destination Key
  3201. //
  3202. hKeyDest = OpenRegistryKey(
  3203. HKEY_LOCAL_MACHINE,
  3204. strDestSubKeyName,
  3205. TRUE, // create
  3206. KEY_WRITE);
  3207. if (!hKeyDest)
  3208. {
  3209. dwRet = GetLastError();
  3210. DebugPrintEx(
  3211. DEBUG_ERR,
  3212. TEXT("OpenRegistryKey failed [%lu], Can't copy keys."),
  3213. dwRet
  3214. );
  3215. goto exit;
  3216. }
  3217. //
  3218. // copy subkeys recursively
  3219. //
  3220. dwRet = SHCopyKey(
  3221. hKeySrcHive,
  3222. strSrcSubKeyName,
  3223. hKeyDest,
  3224. 0);
  3225. if ( ERROR_SUCCESS != dwRet )
  3226. {
  3227. DebugPrintEx(
  3228. DEBUG_ERR,
  3229. TEXT("SHCopyKey failed with [%ld]"),
  3230. dwRet);
  3231. goto exit;
  3232. }
  3233. Assert(ERROR_SUCCESS == dwRet);
  3234. exit:
  3235. if (NULL != hKeyDest)
  3236. {
  3237. if(ERROR_SUCCESS != RegCloseKey(hKeyDest))
  3238. {
  3239. DebugPrintEx(DEBUG_ERR,
  3240. TEXT("RegCloseKey failed (ec=%iu)"),
  3241. GetLastError());
  3242. }
  3243. }
  3244. return dwRet;
  3245. } // FaxCopyRegSubkeys
  3246. /*++
  3247. Routine name : MoveDeviceRegIntoDeviceCache
  3248. Routine description:
  3249. Move device's service and TAPI data into device cache
  3250. Author:
  3251. Caliv Nir (t-nicali), Apr, 2001
  3252. Arguments:
  3253. dwServerPermanentID [in] - service device ID
  3254. dwTapiPermanentLineID [in] - tapi devive ID
  3255. fManualAnswer [in] - TRUE if the device was set to manual answer
  3256. Return Value:
  3257. ERROR_SUCCESS - on succesful move
  3258. win32 error code on failure
  3259. --*/
  3260. DWORD
  3261. MoveDeviceRegIntoDeviceCache(
  3262. DWORD dwServerPermanentID,
  3263. DWORD dwTapiPermanentLineID,
  3264. BOOL fManualAnswer
  3265. )
  3266. {
  3267. DWORD ec = ERROR_SUCCESS; // LastError for this function.
  3268. HKEY hKey = NULL;
  3269. TCHAR strSrcSubKeyName [MAX_PATH];
  3270. TCHAR strDestSubKeyName[MAX_PATH];
  3271. DWORDLONG dwlTimeNow;
  3272. DEBUG_FUNCTION_NAME(TEXT("MoveDeviceRegIntoDeviceCache"));
  3273. //
  3274. // open/create - "fax\Device Cache\GUID" Registry Key
  3275. // and create new key for the device using the dwTapiPermanentLineID as a key
  3276. // server data is stored under service GUID
  3277. //
  3278. _stprintf( strDestSubKeyName, TEXT("%s\\%08lx\\%s"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID, REGKEY_FAXSVC_DEVICE_GUID );
  3279. //
  3280. // open - "fax\Devices" Registry Key
  3281. //
  3282. _stprintf( strSrcSubKeyName, TEXT("%s\\%010lu\\%s"), REGKEY_FAX_DEVICES, dwServerPermanentID, REGKEY_FAXSVC_DEVICE_GUID );
  3283. ec = FaxCopyRegSubkeys(strDestSubKeyName,HKEY_LOCAL_MACHINE,strSrcSubKeyName);
  3284. if ( ERROR_SUCCESS != ec )
  3285. {
  3286. DebugPrintEx(
  3287. DEBUG_ERR,
  3288. TEXT("FaxCopyRegSubkeys of service data failed with [%ld] for tapi ID [%lu]. abort movement"),
  3289. ec,
  3290. dwTapiPermanentLineID
  3291. );
  3292. return ec;
  3293. }
  3294. //
  3295. // If the device was a manual answer device, set it in the registry
  3296. // open - "fax\Device Cache\dwTapiPermanentLineID" Registry Key
  3297. //
  3298. _stprintf( strDestSubKeyName, TEXT("%s\\%08lx"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID);
  3299. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, strDestSubKeyName, FALSE, KEY_WRITE );
  3300. if (hKey)
  3301. {
  3302. SetRegistryDword( hKey, REGVAL_MANUAL_ANSWER, fManualAnswer );
  3303. RegCloseKey(hKey);
  3304. }
  3305. else
  3306. {
  3307. DebugPrintEx( DEBUG_ERR,
  3308. TEXT("OpenRegistryKey failed with [%lu] for [%s]."),
  3309. GetLastError(),
  3310. strDestSubKeyName);
  3311. }
  3312. ec = DeleteDeviceEntry(dwServerPermanentID);
  3313. if ( ERROR_SUCCESS != ec )
  3314. {
  3315. DebugPrintEx(
  3316. DEBUG_WRN,
  3317. TEXT("DeleteDeviceEntry of service data failed with [%ld] for tapi ID [%lu]. continue movement"),
  3318. ec,
  3319. dwTapiPermanentLineID
  3320. );
  3321. }
  3322. //
  3323. // open/create - "fax\Device Cache\TAPI Data" Registry Key
  3324. // and create new key for the device using the dwTapiPermanentLineID as a key
  3325. //
  3326. _stprintf( strDestSubKeyName, TEXT("%s\\%08lx\\%s"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID, REGKEY_TAPI_DATA );
  3327. //
  3328. // open - "fax\TAPIDevices" Registry Key
  3329. //
  3330. _stprintf( strSrcSubKeyName, TEXT("%s\\%08lx"), REGKEY_TAPIDEVICES, dwTapiPermanentLineID );
  3331. ec = FaxCopyRegSubkeys(strDestSubKeyName,HKEY_LOCAL_MACHINE,strSrcSubKeyName);
  3332. if ( ERROR_SUCCESS != ec )
  3333. {
  3334. DebugPrintEx(
  3335. DEBUG_WRN,
  3336. TEXT("FaxCopyRegSubkeys of TAPI data failed with [%ld] for tapi ID [%lu]."),
  3337. ec,
  3338. dwTapiPermanentLineID
  3339. );
  3340. }
  3341. ec = DeleteTapiEntry(dwTapiPermanentLineID);
  3342. if ( ERROR_SUCCESS != ec )
  3343. {
  3344. DebugPrintEx(
  3345. DEBUG_WRN,
  3346. TEXT("DeleteTapiEntry of service data failed with [%ld] for tapi ID [%lu]."),
  3347. ec,
  3348. dwTapiPermanentLineID
  3349. );
  3350. }
  3351. //
  3352. // Mark cache entry creation time
  3353. //
  3354. GetSystemTimeAsFileTime((FILETIME *)&dwlTimeNow);
  3355. if ( FALSE == UpdateLastDetectedTime(dwTapiPermanentLineID,dwlTimeNow) )
  3356. {
  3357. // the entry will be delete in the next service startup
  3358. DebugPrintEx(
  3359. DEBUG_WRN,
  3360. TEXT("UpdateLastDetectedTime failed for device cache ID no. [%lu]."),
  3361. dwTapiPermanentLineID
  3362. );
  3363. }
  3364. // service device data has been moved
  3365. return ERROR_SUCCESS;
  3366. }
  3367. /*++
  3368. Routine name : RestoreDeviceRegFromDeviceCache
  3369. Routine description:
  3370. restore a device data from device cache, into devices
  3371. Author:
  3372. Caliv Nir (t-nicali), Apr, 2001
  3373. Arguments:
  3374. dwServerPermanentID [in] - service device ID
  3375. dwTapiPermanentLineID [in] - tapi devive ID
  3376. Return Value:
  3377. ERROR_SUCCESS - on succesful move
  3378. win32 error code on failure
  3379. --*/
  3380. DWORD
  3381. RestoreDeviceRegFromDeviceCache(DWORD dwServerPermanentID,DWORD dwTapiPermanentLineID)
  3382. {
  3383. DWORD ec = ERROR_SUCCESS; // LastError for this function.
  3384. HKEY hKey = NULL;
  3385. HKEY hKeySrc = NULL;
  3386. TCHAR strSrcSubKeyName [MAX_PATH];
  3387. TCHAR strDestSubKeyName[MAX_PATH];
  3388. BOOL fFaxDevicesKeyCreated = FALSE;
  3389. DEBUG_FUNCTION_NAME(TEXT("RestoreDeviceRegFromDeviceCache"));
  3390. //
  3391. // Restore Service date
  3392. //
  3393. //
  3394. // "fax\Device Cache\dwTapiPermanentLineID\REGKEY_FAXSVC_DEVICE_GUID" Registry Key
  3395. //
  3396. _stprintf( strSrcSubKeyName, TEXT("%s\\%08lx\\%s"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID, REGKEY_FAXSVC_DEVICE_GUID );
  3397. //
  3398. // "fax\Devices\dwServerPermanentID\REGKEY_FAXSVC_DEVICE_GUID" Registry Key
  3399. //
  3400. _stprintf( strDestSubKeyName, TEXT("%s\\%010lu\\%s"), REGKEY_FAX_DEVICES, dwServerPermanentID, REGKEY_FAXSVC_DEVICE_GUID );
  3401. ec = FaxCopyRegSubkeys(strDestSubKeyName,HKEY_LOCAL_MACHINE,strSrcSubKeyName);
  3402. if ( ERROR_SUCCESS != ec )
  3403. {
  3404. DebugPrintEx(
  3405. DEBUG_ERR,
  3406. TEXT("FaxCopyRegSubkeys of service data failed with [%lu] for tapi ID [%lu]. abort movement"),
  3407. ec,
  3408. dwTapiPermanentLineID
  3409. );
  3410. goto Exit;
  3411. }
  3412. fFaxDevicesKeyCreated = TRUE;
  3413. //
  3414. // open - "fax\Devices\dwServerPermanentID" Registry Key
  3415. //
  3416. _stprintf( strSrcSubKeyName, TEXT("%s\\%010lu"), REGKEY_FAX_DEVICES, dwServerPermanentID);
  3417. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, strSrcSubKeyName, FALSE, KEY_WRITE);
  3418. if (!hKey)
  3419. {
  3420. ec = GetLastError();
  3421. DebugPrintEx(
  3422. DEBUG_ERR,
  3423. TEXT("OpenRegistryKey failed with [%lu] for [%s]. abort movement"),
  3424. ec,
  3425. strSrcSubKeyName
  3426. );
  3427. goto Exit;
  3428. }
  3429. //
  3430. // store "Permanent Lineid" value
  3431. //
  3432. if ( FALSE == SetRegistryDword(hKey, REGVAL_PERMANENT_LINEID, dwServerPermanentID) )
  3433. {
  3434. ec = GetLastError();
  3435. DebugPrintEx(
  3436. DEBUG_ERR,
  3437. TEXT("SetRegistryDword failed for [%s]. abort movement"),
  3438. REGVAL_PERMANENT_LINEID
  3439. );
  3440. goto Exit;
  3441. }
  3442. //
  3443. // Restore TAPI data
  3444. //
  3445. //
  3446. // open - "fax\Device Cache\dwTapiPermanentLineID\TAPI Data" Registry Key
  3447. //
  3448. _stprintf( strSrcSubKeyName, TEXT("%s\\%08lx\\%s"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID, REGKEY_TAPI_DATA );
  3449. //
  3450. // open/create - "fax\TAPIDevices\dwTapiPermanentLineID" Registry Key
  3451. //
  3452. _stprintf( strDestSubKeyName, TEXT("%s\\%08lx"), REGKEY_TAPIDEVICES, dwTapiPermanentLineID );
  3453. //
  3454. // See if fax\Device Cache\dwTapiPermanentLineID\TAPI Data exists
  3455. //
  3456. hKeySrc = OpenRegistryKey( HKEY_LOCAL_MACHINE, strSrcSubKeyName, FALSE, KEY_READ );
  3457. if (!hKeySrc)
  3458. {
  3459. //
  3460. // This data does not have to be there
  3461. //
  3462. DebugPrintEx(
  3463. DEBUG_WRN,
  3464. TEXT("OpenRegistryKey failed with [%lu], Can't copy keys."),
  3465. GetLastError());
  3466. }
  3467. else
  3468. {
  3469. //
  3470. // fax\Device Cache\dwTapiPermanentLineID\TAPI Data exists, try to copy data
  3471. //
  3472. RegCloseKey(hKeySrc);
  3473. ec = FaxCopyRegSubkeys(strDestSubKeyName,HKEY_LOCAL_MACHINE, strSrcSubKeyName);
  3474. if ( ERROR_SUCCESS != ec)
  3475. {
  3476. DebugPrintEx(
  3477. DEBUG_WRN,
  3478. TEXT("FaxCopyRegSubkeys of TAPI data failed with [%lu] for tapi ID [%lu]."),
  3479. ec,
  3480. dwTapiPermanentLineID
  3481. );
  3482. goto Exit;
  3483. }
  3484. }
  3485. Assert (ERROR_SUCCESS == ec);
  3486. Exit:
  3487. if (NULL != hKey)
  3488. {
  3489. RegCloseKey(hKey);
  3490. }
  3491. if (ERROR_SUCCESS != ec &&
  3492. TRUE == fFaxDevicesKeyCreated)
  3493. {
  3494. //
  3495. // Delete the registry entry fax\Devices\dwServerPermanentID
  3496. //
  3497. DWORD dwRes = DeleteDeviceEntry(dwServerPermanentID);
  3498. if (ERROR_SUCCESS != dwRes)
  3499. {
  3500. DebugPrintEx(
  3501. DEBUG_ERR,
  3502. TEXT("DeleteDeviceEntry failed with [%lu] for server ID [%lu]."),
  3503. dwRes,
  3504. dwServerPermanentID
  3505. );
  3506. }
  3507. }
  3508. DeleteCacheEntry(dwTapiPermanentLineID);
  3509. return ec;
  3510. }
  3511. /*++
  3512. Routine name : FindServiceDeviceByTapiPermanentLineID
  3513. Routine description:
  3514. Search for a device configuration in the registry with a given "Tapi Permanent Line ID"
  3515. and the device's name. and return it's service ID and REG_SETUP data
  3516. Author:
  3517. Caliv Nir (t-nicali), Mar, 2001
  3518. Updated:
  3519. Apr, 2001 - Device cache re-implementation
  3520. Arguments:
  3521. dwTapiPermanentLineID [in] - Tapi Permanent Line ID to search
  3522. strDeviceName [in] - Device name
  3523. pRegSetup [out] - Parameter, for returning registry stored Csid, Tsid, Flags, Rings
  3524. pInputFaxReg [in] - Devices list (from GetFaxDevicesRegistry() )
  3525. Return Value:
  3526. Permanent Line ID (server's ID) or 0 if not found
  3527. --*/
  3528. DWORD
  3529. FindServiceDeviceByTapiPermanentLineID(
  3530. DWORD dwTapiPermanentLineID,
  3531. LPCTSTR strDeviceName,
  3532. PREG_SETUP pRegSetup,
  3533. const PREG_FAX_DEVICES pInputFaxReg
  3534. )
  3535. {
  3536. DWORD dwDevice;
  3537. DWORD dwServiceID = 0;
  3538. DEBUG_FUNCTION_NAME(TEXT("FindServiceDeviceByTapiPermanentLineID"));
  3539. Assert( pRegSetup );
  3540. Assert( pInputFaxReg );
  3541. // iterate through all devices and try to find the device with the given TapiPermanentLineID and name
  3542. for ( dwDevice = 0 ; dwDevice < pInputFaxReg->DeviceCount ; ++dwDevice )
  3543. {
  3544. PREG_DEVICE pRegDevice = &(pInputFaxReg->Devices[dwDevice]);
  3545. if(!pRegDevice->bValidDevice)
  3546. {
  3547. // the device's registry record is not valid
  3548. continue;
  3549. }
  3550. // it's the same device if permanent Tapi line ID and the device name are equal.
  3551. if ( pRegDevice->TapiPermanentLineID == dwTapiPermanentLineID &&
  3552. (0 == _tcscmp(strDeviceName,pRegDevice->lptstrDeviceName)) )
  3553. {
  3554. // update REG_SETUP record with the registry values
  3555. LPTSTR strTemp = NULL;
  3556. if ( NULL != (strTemp = StringDup(pRegDevice->Csid) ) )
  3557. {
  3558. MemFree(pRegSetup->Csid);
  3559. pRegSetup->Csid = strTemp;
  3560. }
  3561. if ( NULL != (strTemp = StringDup(pRegDevice->Tsid) ) )
  3562. {
  3563. MemFree(pRegSetup->Tsid);
  3564. pRegSetup->Tsid = strTemp;
  3565. }
  3566. if ( NULL != (strTemp = StringDup(pRegDevice->lptstrDescription) ) )
  3567. {
  3568. MemFree(pRegSetup->lptstrDescription);
  3569. pRegSetup->lptstrDescription = strTemp;
  3570. }
  3571. pRegSetup->Flags = pRegDevice->Flags;
  3572. pRegSetup->Rings = pRegDevice->Rings;
  3573. dwServiceID = pRegDevice->PermanentLineId; // server's line ID (also the key of the device in the registry)
  3574. pRegDevice->DeviceInstalled = TRUE; // mark as installed, will be needed later for registry clean-up
  3575. break; // found it no need to continue
  3576. }
  3577. }
  3578. return dwServiceID;
  3579. }
  3580. /*++
  3581. Routine name : FindCacheEntryByTapiPermanentLineID
  3582. Routine description:
  3583. Search for a device configuration in the registry Device cache with a given "Tapi Permanent Line ID"
  3584. and the device's name.
  3585. Author:
  3586. Caliv Nir (t-nicali), Apr, 2001
  3587. Arguments:
  3588. dwTapiPermanentLineID [in] - Tapi Permanent Line ID to search
  3589. strDeviceName [in] - Device name
  3590. pRegSetup [out] - Parameter, for returning registry stored Csid, Tsid, Flags, Rings
  3591. lpdwLastUniqueLineId [in] - last unique Server device ID (from registry), for assigning the device with new ID
  3592. pfManualAnswer [out] - TRUE if the device was wet to manual answer when moved to the cache
  3593. Return Value:
  3594. Permanent Line ID (server's ID) or 0 if not found
  3595. --*/
  3596. DWORD
  3597. FindCacheEntryByTapiPermanentLineID(
  3598. DWORD dwTapiPermanentLineID,
  3599. LPCTSTR strDeviceName,
  3600. PREG_SETUP pRegSetup,
  3601. LPDWORD lpdwLastUniqueLineId,
  3602. BOOL* pfManualAnswer
  3603. )
  3604. {
  3605. DWORD dwNewServiceID = 0;
  3606. HKEY hKey = NULL;
  3607. TCHAR SubKeyName[MAX_PATH];
  3608. LPTSTR strDeviceNameFromCache=NULL;
  3609. BOOL fManualAnswer = FALSE;
  3610. DEBUG_FUNCTION_NAME(TEXT("FindCacheEntryByTapiPermanentLineID"));
  3611. //
  3612. // open - "fax\Device Cache\dwTapiPermanentLineID\REGKEY_FAXSVC_DEVICE_GUID" Registry Key
  3613. //
  3614. _stprintf( SubKeyName, TEXT("%s\\%08lx\\%s"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID, REGKEY_FAXSVC_DEVICE_GUID );
  3615. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, FALSE, KEY_READ );
  3616. if (!hKey)
  3617. {
  3618. return dwNewServiceID;
  3619. }
  3620. //
  3621. // found the dwTapiPermanentLineID inside the cache now check the device's name
  3622. //
  3623. Assert(strDeviceName);
  3624. strDeviceNameFromCache=GetRegistryString(hKey,REGVAL_DEVICE_NAME,NULL);
  3625. if ( (NULL != strDeviceNameFromCache) &&
  3626. (0 == _tcscmp(strDeviceName,strDeviceNameFromCache)) )
  3627. {
  3628. //
  3629. // found the device entry in cache
  3630. //
  3631. if ( ERROR_SUCCESS != GetNewServiceDeviceID(lpdwLastUniqueLineId, &dwNewServiceID))
  3632. {
  3633. DebugPrintEx(
  3634. DEBUG_ERR,
  3635. TEXT("GetNewServiceDeviceID failed and couldn't assign new Service ID")
  3636. );
  3637. dwNewServiceID = 0;
  3638. }
  3639. }
  3640. if (hKey)
  3641. {
  3642. RegCloseKey(hKey);
  3643. }
  3644. MemFree(strDeviceNameFromCache);
  3645. if ( dwNewServiceID )
  3646. {
  3647. //
  3648. // Chcek if the device was set to manual answer
  3649. // open - "fax\Device Cache\dwTapiPermanentLineID" Registry Key
  3650. //
  3651. _stprintf( SubKeyName, TEXT("%s\\%08lx"), REGKEY_FAX_DEVICES_CACHE, dwTapiPermanentLineID);
  3652. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, FALSE, KEY_READ );
  3653. if (hKey)
  3654. {
  3655. fManualAnswer = GetRegistryDword( hKey, REGVAL_MANUAL_ANSWER );
  3656. RegCloseKey(hKey);
  3657. }
  3658. *pfManualAnswer = fManualAnswer;
  3659. //
  3660. // move the cahce entry into devices
  3661. //
  3662. if ( ERROR_SUCCESS == RestoreDeviceRegFromDeviceCache(dwNewServiceID,dwTapiPermanentLineID) )
  3663. {
  3664. //
  3665. // update REG_SETUP record with the registry values
  3666. //
  3667. Assert( pRegSetup );
  3668. _stprintf( SubKeyName, TEXT("%s\\%010lu\\%s"), REGKEY_FAX_DEVICES, dwNewServiceID, REGKEY_FAXSVC_DEVICE_GUID );
  3669. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, FALSE, KEY_READ );
  3670. if (!hKey) {
  3671. DebugPrintEx(
  3672. DEBUG_ERR,
  3673. TEXT("OpenRegistryKey failed for [%s]. REG_SETUP was not updated."),
  3674. SubKeyName
  3675. );
  3676. //
  3677. // return the new service ID but REG_SETUP will contains it's default values
  3678. //
  3679. return dwNewServiceID;
  3680. }
  3681. LPTSTR strTemp = NULL;
  3682. if ( NULL != (strTemp = GetRegistryString( hKey, REGVAL_ROUTING_CSID, REGVAL_DEFAULT_CSID )) )
  3683. {
  3684. MemFree(pRegSetup->Csid);
  3685. pRegSetup->Csid = strTemp;
  3686. }
  3687. if ( NULL != (strTemp = GetRegistryString( hKey, REGVAL_ROUTING_TSID, REGVAL_DEFAULT_TSID )) )
  3688. {
  3689. MemFree(pRegSetup->Tsid);
  3690. pRegSetup->Tsid = strTemp;
  3691. }
  3692. if ( NULL != (strTemp = GetRegistryString( hKey, REGVAL_DEVICE_DESCRIPTION, EMPTY_STRING )) )
  3693. {
  3694. MemFree(pRegSetup->lptstrDescription);
  3695. pRegSetup->lptstrDescription = strTemp;
  3696. }
  3697. pRegSetup->Flags = GetRegistryDword( hKey, REGVAL_FLAGS );
  3698. pRegSetup->Rings = GetRegistryDword( hKey, REGVAL_RINGS );
  3699. RegCloseKey(hKey);
  3700. }
  3701. else
  3702. {
  3703. //
  3704. // couldn't restore the device cache entry
  3705. //
  3706. dwNewServiceID = 0;
  3707. }
  3708. }
  3709. return dwNewServiceID;
  3710. }
  3711. /*++
  3712. Routine name : GetNewServiceDeviceID
  3713. Routine description:
  3714. The routine search and return new Service device ID.
  3715. The routine also update this new ID in registry
  3716. ReImplemented By:
  3717. Caliv Nir (t-nicali), Apr, 2001
  3718. Arguments:
  3719. lpdwLastUniqueLineId [in/out] - last ID given to service device (from registry)
  3720. lpdwPermanentLineId [out] - on success will contain the new ID
  3721. Return Value:
  3722. ERROR_SUCCESS - when ID was successfully assigned
  3723. on failue - win32 error code
  3724. --*/
  3725. DWORD
  3726. GetNewServiceDeviceID(
  3727. LPDWORD lpdwLastUniqueLineId,
  3728. LPDWORD lpdwPermanentLineId
  3729. )
  3730. {
  3731. //
  3732. // Create a new UniqueLineInd.
  3733. // A fax unique line id is always below the base of the FSP line ids.
  3734. //
  3735. DWORD dwUniqueDeviceIdsSpace = DEFAULT_REGVAL_PROVIDER_DEVICE_ID_PREFIX_BASE - DEFAULT_REGVAL_FAX_UNIQUE_DEVICE_ID_BASE;
  3736. DWORD bGeneratedId = FALSE;
  3737. DWORD dwRes = ERROR_SUCCESS;
  3738. TCHAR SubKeyName[MAX_PATH];
  3739. HKEY hKey = NULL;
  3740. DEBUG_FUNCTION_NAME(TEXT("GetNewServiceDeviceID"));
  3741. //
  3742. // Scan through all available space
  3743. //
  3744. if (*lpdwLastUniqueLineId < DEFAULT_REGVAL_FAX_UNIQUE_DEVICE_ID_BASE)
  3745. {
  3746. //
  3747. // Set to minimum. May happen only in first attempt.
  3748. //
  3749. *lpdwLastUniqueLineId = DEFAULT_REGVAL_FAX_UNIQUE_DEVICE_ID_BASE;
  3750. }
  3751. DWORD dwAttempt;
  3752. for (dwAttempt = 0; dwAttempt< dwUniqueDeviceIdsSpace; dwAttempt++)
  3753. {
  3754. (*lpdwLastUniqueLineId)++;
  3755. if (*lpdwLastUniqueLineId >= DEFAULT_REGVAL_PROVIDER_DEVICE_ID_PREFIX_BASE)
  3756. {
  3757. //
  3758. // Reached space height limit, loop back to lower limit.
  3759. //
  3760. *lpdwLastUniqueLineId = DEFAULT_REGVAL_FAX_UNIQUE_DEVICE_ID_BASE;
  3761. continue;
  3762. }
  3763. Assert(*lpdwLastUniqueLineId != 0);
  3764. Assert(*lpdwLastUniqueLineId < DEFAULT_REGVAL_PROVIDER_DEVICE_ID_PREFIX_BASE);
  3765. Assert(*lpdwLastUniqueLineId >= DEFAULT_REGVAL_FAX_UNIQUE_DEVICE_ID_BASE);
  3766. _stprintf( SubKeyName, TEXT("%s\\%010d"), REGKEY_FAX_DEVICES, *lpdwLastUniqueLineId );
  3767. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKeyName, FALSE, KEY_READ );
  3768. if (!hKey)
  3769. {
  3770. bGeneratedId = TRUE;
  3771. break;
  3772. }
  3773. else
  3774. {
  3775. RegCloseKey( hKey );
  3776. }
  3777. }
  3778. if (hKey)
  3779. {
  3780. RegCloseKey( hKey );
  3781. }
  3782. if (!bGeneratedId)
  3783. {
  3784. DebugPrintEx(
  3785. DEBUG_ERR,
  3786. TEXT("Failed to generate next uniqueu line id."));
  3787. return E_FAIL;
  3788. }
  3789. //
  3790. // Persiste the new line id
  3791. //
  3792. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAXSERVER, TRUE, KEY_WRITE );
  3793. if (!hKey)
  3794. {
  3795. dwRes = GetLastError();
  3796. DebugPrintEx(
  3797. DEBUG_ERR,
  3798. TEXT("OpenRegistryKey Failed for %s while persisting new unique line id (%010d) (ec: %ld)"),
  3799. REGKEY_FAX_DEVICES,
  3800. *lpdwLastUniqueLineId,
  3801. dwRes);
  3802. return dwRes;
  3803. }
  3804. if (!SetRegistryDword( hKey, REGVAL_LAST_UNIQUE_LINE_ID, *lpdwLastUniqueLineId))
  3805. {
  3806. dwRes = GetLastError();
  3807. DebugPrintEx(
  3808. DEBUG_ERR,
  3809. TEXT("SetRegistryDword to value [%s] failed while writing new unique line id (%010d) (ec: %ld)"),
  3810. REGVAL_LAST_UNIQUE_LINE_ID,
  3811. *lpdwLastUniqueLineId,
  3812. dwRes );
  3813. RegCloseKey (hKey);
  3814. return dwRes;
  3815. }
  3816. RegCloseKey (hKey);
  3817. *lpdwPermanentLineId = *lpdwLastUniqueLineId;
  3818. return dwRes;
  3819. }
  3820. /*++
  3821. Routine name : UpdateLastDetectedTime
  3822. Routine description:
  3823. Write creation time of a cache entry for a given TAPI line ID
  3824. ReImplemented By:
  3825. Caliv Nir (t-nicali), Apr, 2001
  3826. Arguments:
  3827. dwPermanentTapiLineID [in] - Permanent Tapi Line ID to update in cache
  3828. dwlTimeNow [in] - Current time in UTC
  3829. Return Value:
  3830. TRUE - on success update.
  3831. FALSE - on failure
  3832. --*/
  3833. BOOL
  3834. UpdateLastDetectedTime(
  3835. DWORD dwPermanentTapiLineID,
  3836. DWORDLONG dwlTimeNow
  3837. )
  3838. {
  3839. BOOL success = FALSE;
  3840. TCHAR SubKey[MAX_PATH];
  3841. HKEY hKey;
  3842. DEBUG_FUNCTION_NAME(TEXT("UpdateLastDetectedTime"));
  3843. _stprintf( SubKey, TEXT("%s\\%08lx"),
  3844. REGKEY_FAX_DEVICES_CACHE,
  3845. dwPermanentTapiLineID);
  3846. // open the device cache entry
  3847. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, SubKey, FALSE, KEY_WRITE );
  3848. if(hKey)
  3849. {
  3850. // try to update the creation time
  3851. success = SetRegistryBinary(hKey, REGVAL_LAST_DETECTED_TIME, (BYTE *)&dwlTimeNow, sizeof(dwlTimeNow));
  3852. RegCloseKey(hKey);
  3853. }
  3854. return success;
  3855. }