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.

1746 lines
50 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // iasmdbtool.cpp
  8. //
  9. // Abstract:
  10. //
  11. // dump the "Properties" table from ias.mdb to a text format
  12. // and also restore ias.mdb from such dump
  13. // saves and restore the reg keys too.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. #include <string>
  18. #include <shlwapi.h>
  19. #include "datastore2.h"
  20. using namespace std;
  21. //////////////////////////////////////////////////////////////////////////////
  22. HRESULT IASExpandString(const wchar_t* pInputString, wchar_t** ppOutputString);
  23. //////////////////////////////////////////////////////////////////////////////
  24. #ifdef DEBUG
  25. #define CHECK_CALL_HRES(expr) \
  26. hres = expr; \
  27. if (FAILED(hres)) \
  28. { \
  29. wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
  30. return hres; \
  31. }
  32. #define CHECK_CALL_HRES_NO_RETURN(expr) \
  33. hres = expr; \
  34. if (FAILED(hres)) \
  35. { \
  36. wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
  37. }
  38. #define CHECK_CALL_HRES_BREAK(expr) \
  39. hres = expr; \
  40. if (FAILED(hres)) \
  41. { \
  42. wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
  43. break; \
  44. }
  45. #else //no printf, only the error code return if needed
  46. #define CHECK_CALL_HRES(expr) \
  47. hres = expr; \
  48. if (FAILED(hres)) \
  49. { \
  50. return hres; \
  51. }
  52. #define CHECK_CALL_HRES_NO_RETURN(expr) \
  53. hres = expr;
  54. #define CHECK_CALL_HRES_BREAK(expr) \
  55. hres = expr; \
  56. if (FAILED(hres)) break;
  57. #endif //DEBUG
  58. #define celems(_x) (sizeof(_x) / sizeof(_x[0]))
  59. #ifdef DBG
  60. #define IgnoreVariable(v) { (v) = (v); }
  61. #else
  62. #define IgnoreVariable(v)
  63. #endif
  64. namespace
  65. {
  66. const int SIZELINEMAX = 512;
  67. const int SIZE_LONG_MAX = 33;
  68. // Number of files generated
  69. // here one: backup.mdb
  70. const int MAX_FILES = 1;
  71. const int EXTRA_CHAR_SPACE = 32;
  72. // file order
  73. const int BACKUP_NB = 0;
  74. const int BINARY_NB = 100;
  75. // that's a lot
  76. const int DECOMPRESS_FACTOR = 100;
  77. const int FILE_BUFFER_SIZE = 1024;
  78. struct IASKEY
  79. {
  80. const wchar_t* c_wcKey;
  81. const wchar_t* c_wcValue;
  82. DWORD c_dwType;
  83. } IAS_Key_Struct;
  84. IASKEY c_wcKEYS[] =
  85. {
  86. {
  87. L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
  88. L"Allow SNMP Set",
  89. REG_DWORD
  90. },
  91. {
  92. L"SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn",
  93. L"DefaultDomain",
  94. REG_SZ
  95. },
  96. {
  97. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
  98. L"MaxDenials",
  99. REG_DWORD
  100. },
  101. {
  102. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
  103. L"ResetTime (mins)",
  104. REG_DWORD
  105. },
  106. {
  107. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  108. L"Allow LM Authentication",
  109. REG_DWORD
  110. },
  111. {
  112. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  113. L"Default User Identity",
  114. REG_SZ
  115. },
  116. {
  117. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  118. L"User Identity Attribute",
  119. REG_DWORD
  120. },
  121. {
  122. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  123. L"Override User-Name",
  124. REG_DWORD
  125. },
  126. {
  127. L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
  128. L"Ping User-Name",
  129. REG_SZ
  130. },
  131. };
  132. const wchar_t c_wcKEYS_FILE[] = L"%TEMP%\\";
  133. #ifdef _WIN64
  134. const wchar_t c_wcIAS_MDB_FILE_NAME[] =
  135. L"%SystemRoot%\\SysWow64\\ias\\ias.mdb";
  136. const wchar_t c_wcIAS_OLD[] = L"%SystemRoot%\\SysWow64\\ias\\iasold.mdb";
  137. #else
  138. const wchar_t c_wcIAS_MDB_FILE_NAME[] =
  139. L"%SystemRoot%\\System32\\ias\\ias.mdb";
  140. const wchar_t c_wcIAS_OLD[] = L"%SystemRoot%\\System32\\ias\\iasold.mdb";
  141. #endif
  142. const wchar_t c_wcFILE_BACKUP[] = L"%TEMP%\\Backup.mdb";
  143. const wchar_t c_wcSELECT_PROPERTIES_INTO[] =
  144. L"SELECT * "
  145. L"INTO Properties IN "
  146. L"\"%TEMP%\\Backup.mdb\" "
  147. L"FROM Properties;";
  148. const wchar_t c_wcSELECT_OBJECTS_INTO[] =
  149. L"SELECT * "
  150. L"INTO Objects IN "
  151. L"\"%TEMP%\\Backup.mdb\" "
  152. L"FROM Objects;";
  153. const wchar_t c_wcSELECT_VERSION_INTO[] =
  154. L"SELECT * "
  155. L"INTO Version IN "
  156. L"\"%TEMP%\\Backup.mdb\" "
  157. L"FROM Version;";
  158. }
  159. //////////////////////////////////////////////////////////////////////////////
  160. //
  161. // WideToAnsi
  162. //
  163. // CALLED BY:everywhere
  164. //
  165. // PARAMETERS: lpStr - destination string
  166. // lpWStr - string to convert
  167. // cchStr - size of dest buffer
  168. //
  169. // DESCRIPTION:
  170. // converts unicode lpWStr to ansi lpStr.
  171. // fills in unconvertable chars w/ DPLAY_DEFAULT_CHAR "-"
  172. //
  173. //
  174. // RETURNS: if cchStr is 0, returns the size required to hold the string
  175. // otherwise, returns the number of chars converted
  176. //
  177. //////////////////////////////////////////////////////////////////////////////
  178. int WideToAnsi(char* lpStr,unsigned short* lpWStr, int cchStr)
  179. {
  180. BOOL bDefault;
  181. // use the default code page (CP_ACP)
  182. // -1 indicates WStr must be null terminated
  183. return WideCharToMultiByte(GetConsoleOutputCP(),0,lpWStr,-1,lpStr,cchStr,"-",&bDefault);
  184. }
  185. /////////////////////////////////////////////////////////////////////////////
  186. //
  187. // IASEnableBackupPrivilege
  188. //
  189. /////////////////////////////////////////////////////////////////////////////
  190. HRESULT IASEnableBackupPrivilege()
  191. {
  192. LONG lResult = ERROR_SUCCESS;
  193. HANDLE hToken = NULL;
  194. do
  195. {
  196. if ( ! OpenProcessToken(
  197. GetCurrentProcess(),
  198. TOKEN_ADJUST_PRIVILEGES,
  199. &hToken
  200. ))
  201. {
  202. lResult = ERROR_CAN_NOT_COMPLETE;
  203. break;
  204. }
  205. LUID luidB;
  206. if ( ! LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &luidB))
  207. {
  208. lResult = ERROR_CAN_NOT_COMPLETE;
  209. break;
  210. }
  211. LUID luidR;
  212. if ( ! LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &luidR))
  213. {
  214. lResult = ERROR_CAN_NOT_COMPLETE;
  215. break;
  216. }
  217. TOKEN_PRIVILEGES tp;
  218. tp.PrivilegeCount = 1;
  219. tp.Privileges[0].Luid = luidB;
  220. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  221. if ( ! AdjustTokenPrivileges(
  222. hToken,
  223. FALSE,
  224. &tp,
  225. sizeof(TOKEN_PRIVILEGES),
  226. NULL,
  227. NULL
  228. ) )
  229. {
  230. lResult = ERROR_CAN_NOT_COMPLETE;
  231. break;
  232. }
  233. tp.PrivilegeCount = 1;
  234. tp.Privileges[0].Luid = luidR;
  235. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  236. if ( ! AdjustTokenPrivileges(
  237. hToken,
  238. FALSE,
  239. &tp,
  240. sizeof(TOKEN_PRIVILEGES),
  241. NULL,
  242. NULL
  243. ) )
  244. {
  245. lResult = ERROR_CAN_NOT_COMPLETE;
  246. break;
  247. }
  248. } while (false);
  249. if ( hToken )
  250. {
  251. CloseHandle(hToken);
  252. }
  253. if ( lResult == ERROR_SUCCESS )
  254. {
  255. return S_OK;
  256. }
  257. else
  258. {
  259. return E_FAIL;
  260. }
  261. }
  262. /////////////////////////////////////////////////////////////////////////////
  263. //
  264. // IASSaveRegKeys
  265. //
  266. /////////////////////////////////////////////////////////////////////////////
  267. HRESULT IASSaveRegKeys()
  268. {
  269. ASSERT(celems(c_wcKEYS) != 0);
  270. ////////////////////////////
  271. // Enable backup privilege.
  272. ////////////////////////////
  273. HRESULT hres;
  274. CHECK_CALL_HRES (IASEnableBackupPrivilege());
  275. wchar_t* completeFile;
  276. CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &completeFile));
  277. size_t c_NbKeys = celems(c_wcKEYS);
  278. for ( int i = 0; i < c_NbKeys; ++i )
  279. {
  280. DWORD dwType = 0;
  281. DWORD cbData = SIZELINEMAX / 2;
  282. LPVOID pvData = CoTaskMemAlloc(sizeof(wchar_t) * SIZELINEMAX);
  283. if (!pvData)
  284. {
  285. hres = E_OUTOFMEMORY;
  286. break;
  287. }
  288. DWORD lResult = SHGetValueW(
  289. HKEY_LOCAL_MACHINE,
  290. c_wcKEYS[i].c_wcKey,
  291. c_wcKEYS[i].c_wcValue,
  292. &dwType,
  293. pvData,
  294. &cbData
  295. );
  296. //
  297. // Try to allocate more memory if cbData returned the size needed
  298. //
  299. if ((lResult != ERROR_SUCCESS) && (cbData > SIZELINEMAX))
  300. {
  301. CoTaskMemFree(pvData);
  302. pvData = CoTaskMemAlloc(sizeof(wchar_t) * cbData);
  303. if ( !pvData )
  304. {
  305. hres = E_OUTOFMEMORY;
  306. break;
  307. }
  308. lResult = SHGetValue(
  309. HKEY_LOCAL_MACHINE,
  310. c_wcKEYS[i].c_wcKey,
  311. c_wcKEYS[i].c_wcValue,
  312. &dwType,
  313. pvData,
  314. &cbData
  315. );
  316. if ( lResult != ERROR_SUCCESS )
  317. {
  318. hres = E_OUTOFMEMORY;
  319. CoTaskMemFree(pvData);
  320. break;
  321. }
  322. }
  323. //
  324. // Create the file (in all situations)
  325. //
  326. wstring sFileName(completeFile);
  327. wchar_t buffer[SIZE_LONG_MAX];
  328. _itow(i, buffer, 10); // 10 means base 10
  329. sFileName += buffer;
  330. sFileName += L".txt";
  331. HANDLE hFile = CreateFileW(
  332. sFileName.c_str(),
  333. GENERIC_WRITE,
  334. 0,
  335. NULL,
  336. CREATE_ALWAYS,
  337. FILE_ATTRIBUTE_NORMAL,
  338. NULL
  339. );
  340. if ( hFile == INVALID_HANDLE_VALUE )
  341. {
  342. hres = E_FAIL;
  343. CoTaskMemFree(pvData);
  344. break;
  345. }
  346. //
  347. // lResult = result of SHGetValue
  348. // and might be an error but not
  349. // a memory problem
  350. //
  351. if ( lResult == ERROR_SUCCESS )
  352. {
  353. //
  354. // Wrong data type
  355. //
  356. if ( dwType != c_wcKEYS[i].c_dwType )
  357. {
  358. hres = E_FAIL;
  359. CoTaskMemFree(pvData);
  360. CloseHandle(hFile);
  361. break;
  362. }
  363. else
  364. {
  365. //
  366. // Save the value to the file
  367. //
  368. BYTE* bBuffer = static_cast<BYTE*>(VirtualAlloc
  369. (
  370. NULL,
  371. (cbData > FILE_BUFFER_SIZE)?
  372. cbData:FILE_BUFFER_SIZE,
  373. MEM_COMMIT,
  374. PAGE_READWRITE
  375. ));
  376. if ( !bBuffer )
  377. {
  378. CoTaskMemFree(pvData);
  379. CloseHandle(hFile);
  380. hres = E_FAIL;
  381. break;
  382. }
  383. memset(bBuffer, '\0', (cbData > FILE_BUFFER_SIZE)?
  384. cbData:FILE_BUFFER_SIZE);
  385. if ( REG_SZ == c_wcKEYS[i].c_dwType )
  386. {
  387. wcscpy((wchar_t*)bBuffer, (wchar_t*)pvData);
  388. }
  389. else
  390. {
  391. memcpy(bBuffer, pvData, cbData);
  392. }
  393. CoTaskMemFree(pvData);
  394. DWORD NumberOfBytesWritten;
  395. BOOL bResult = WriteFile(
  396. hFile,
  397. bBuffer,
  398. (cbData > FILE_BUFFER_SIZE)?
  399. cbData:FILE_BUFFER_SIZE,
  400. &NumberOfBytesWritten,
  401. NULL
  402. );
  403. VirtualFree(
  404. bBuffer,
  405. (cbData > FILE_BUFFER_SIZE)?
  406. cbData:FILE_BUFFER_SIZE,
  407. MEM_RELEASE
  408. ); // ignore result
  409. CloseHandle(hFile);
  410. if ( bResult )
  411. {
  412. hres = S_OK;
  413. }
  414. else
  415. {
  416. hres = E_FAIL;
  417. break;
  418. }
  419. }
  420. }
  421. else
  422. {
  423. //
  424. // create an empty file
  425. BYTE bBuffer[FILE_BUFFER_SIZE];
  426. memset(bBuffer, '#', (cbData > FILE_BUFFER_SIZE)?
  427. cbData:FILE_BUFFER_SIZE);
  428. DWORD NumberOfBytesWritten;
  429. BOOL bResult = WriteFile(
  430. hFile,
  431. &bBuffer,
  432. FILE_BUFFER_SIZE,
  433. &NumberOfBytesWritten,
  434. NULL
  435. );
  436. CoTaskMemFree(pvData);
  437. CloseHandle(hFile);
  438. if ( bResult == TRUE )
  439. {
  440. hres = S_OK;
  441. }
  442. else
  443. {
  444. hres = E_FAIL;
  445. break;
  446. }
  447. }
  448. }
  449. ////////////
  450. // Clean
  451. ////////////
  452. CoTaskMemFree(completeFile);
  453. return hres;
  454. }
  455. //////////////////////////////////////////////////////////////////////////////
  456. //
  457. // KeyShouldBeRestored
  458. //
  459. // maps the reg keys to the netsh tokens
  460. /*
  461. L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
  462. L"Allow SNMP Set",
  463. server
  464. L"SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn",
  465. L"DefaultDomain",
  466. rap
  467. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
  468. L"MaxDenials",
  469. server
  470. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
  471. L"ResetTime (mins)",
  472. server
  473. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  474. L"Allow LM Authentication",
  475. rap
  476. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  477. L"Default User Identity",
  478. rap
  479. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  480. L"User Identity Attribute",
  481. rap
  482. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
  483. L"Override User-Name",
  484. rap
  485. L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
  486. L"Ping User-Name",
  487. server
  488. */
  489. //
  490. //////////////////////////////////////////////////////////////////////////////
  491. bool KeyShouldBeRestored(size_t keyIndex, IAS_SHOW_TOKEN_LIST configType)
  492. {
  493. // keyIndex maps to the index of the key in the array of keys
  494. // configType is the token to use.
  495. bool retVal = false;
  496. switch(configType)
  497. {
  498. case CONFIG:
  499. {
  500. // true for everything
  501. retVal = true;
  502. break;
  503. }
  504. case SERVER_SETTINGS:
  505. {
  506. if ( (keyIndex == 0) ||
  507. (keyIndex == 2) ||
  508. (keyIndex == 3) ||
  509. (keyIndex == 8)
  510. )
  511. {
  512. retVal = true;
  513. }
  514. break;
  515. }
  516. case REMOTE_ACCESS_POLICIES:
  517. {
  518. if ( (keyIndex == 1) ||
  519. (keyIndex == 4) ||
  520. (keyIndex == 5) ||
  521. (keyIndex == 6) ||
  522. (keyIndex == 7)
  523. )
  524. {
  525. retVal = true;
  526. }
  527. break;
  528. }
  529. case CONNECTION_REQUEST_POLICIES:
  530. case CLIENTS:
  531. case LOGGING:
  532. default:
  533. {
  534. retVal = false;
  535. break;
  536. }
  537. }
  538. return retVal;
  539. }
  540. //////////////////////////////////////////////////////////////////////////////
  541. //
  542. // IASRestoreRegKeys
  543. //
  544. // if something cannot be restored because of an empty
  545. // backup file (no key saved), that's not an error
  546. //
  547. //////////////////////////////////////////////////////////////////////////////
  548. HRESULT IASRestoreRegKeys(/*in*/ IAS_SHOW_TOKEN_LIST configType)
  549. {
  550. ASSERT(celems(c_wcKEYS) != 0);
  551. ////////////////////////////
  552. // Enable backup privilege.
  553. // and sets hres
  554. ////////////////////////////
  555. HRESULT hres;
  556. CHECK_CALL_HRES (IASEnableBackupPrivilege());
  557. wchar_t* completeFile;
  558. CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &completeFile));
  559. size_t c_NbKeys = celems(c_wcKEYS);
  560. for (size_t i = 0; i < c_NbKeys; ++i )
  561. {
  562. if (!KeyShouldBeRestored(i, configType))
  563. {
  564. continue;
  565. }
  566. wstring sFileName(completeFile);
  567. wchar_t buffer[SIZE_LONG_MAX];
  568. DWORD dwDisposition;
  569. _itow(i, buffer, 10); // 10 means base 10
  570. sFileName += buffer;
  571. sFileName += L".txt";
  572. // open the file
  573. HANDLE hFile = CreateFileW(
  574. sFileName.c_str(),
  575. GENERIC_READ,
  576. 0,
  577. NULL,
  578. OPEN_EXISTING,
  579. FILE_ATTRIBUTE_NORMAL,
  580. NULL
  581. );
  582. if (INVALID_HANDLE_VALUE == hFile)
  583. {
  584. // maybe some reg keys were not saved in that file.
  585. // for instance Ping User-Name wasn't saved.
  586. continue;
  587. }
  588. // check the type of data expected
  589. LPVOID lpBuffer = NULL;
  590. DWORD SizeToRead;
  591. if (REG_SZ == c_wcKEYS[i].c_dwType)
  592. {
  593. lpBuffer = CoTaskMemAlloc(sizeof(wchar_t) * FILE_BUFFER_SIZE);
  594. SizeToRead = FILE_BUFFER_SIZE;
  595. }
  596. else if (REG_DWORD == c_wcKEYS[i].c_dwType)
  597. {
  598. lpBuffer = CoTaskMemAlloc(sizeof(DWORD));
  599. SizeToRead = sizeof(DWORD);
  600. }
  601. else
  602. {
  603. // unknown
  604. ASSERT(FALSE);
  605. }
  606. if (!lpBuffer)
  607. {
  608. CloseHandle(hFile);
  609. hres = E_OUTOFMEMORY;
  610. break;
  611. }
  612. memset(lpBuffer,'\0',SizeToRead);
  613. // read the file
  614. DWORD NumberOfBytesRead;
  615. BOOL b = ReadFile(
  616. hFile,
  617. lpBuffer,
  618. SizeToRead,
  619. &NumberOfBytesRead,
  620. NULL
  621. ); // ignore return value. uses NumberOfBytesRead
  622. // to determine success condition
  623. IgnoreVariable(b);
  624. CloseHandle(hFile);
  625. // check if the file contains ####
  626. if ( NumberOfBytesRead == 0 )
  627. {
  628. // problem
  629. CoTaskMemFree(lpBuffer);
  630. hres = E_FAIL;
  631. break;
  632. }
  633. else
  634. {
  635. BYTE TempBuffer[sizeof(DWORD)];
  636. memset(TempBuffer, '#', sizeof(DWORD));
  637. if (0 == memcmp(lpBuffer, TempBuffer, sizeof(DWORD)))
  638. {
  639. // no key saved, delete existing key if any
  640. HKEY hKeyToDelete = NULL;
  641. if (ERROR_SUCCESS == RegOpenKeyW(
  642. HKEY_LOCAL_MACHINE,
  643. c_wcKEYS[i].c_wcKey,
  644. &hKeyToDelete
  645. ))
  646. {
  647. if (ERROR_SUCCESS != RegDeleteValueW
  648. (
  649. hKeyToDelete,
  650. c_wcKEYS[i].c_wcValue
  651. ))
  652. {
  653. // delete existing key failed\n");
  654. }
  655. RegCloseKey(hKeyToDelete);
  656. }
  657. //
  658. // else do nothing: key doesn't exist
  659. //
  660. }
  661. else
  662. {
  663. // key saved: restore value
  664. // what if the value is bigger than
  665. // the buffer size?
  666. HKEY hKeyToUpdate;
  667. LONG lResult = RegCreateKeyExW(
  668. HKEY_LOCAL_MACHINE,
  669. c_wcKEYS[i].c_wcKey,
  670. 0,
  671. NULL,
  672. REG_OPTION_NON_VOLATILE |
  673. REG_OPTION_BACKUP_RESTORE ,
  674. KEY_ALL_ACCESS,
  675. NULL,
  676. &hKeyToUpdate,
  677. &dwDisposition
  678. );
  679. if (ERROR_SUCCESS != lResult)
  680. {
  681. lResult = RegCreateKeyW(
  682. HKEY_LOCAL_MACHINE,
  683. c_wcKEYS[i].c_wcKey,
  684. &hKeyToUpdate
  685. );
  686. if (ERROR_SUCCESS != lResult)
  687. {
  688. RegCloseKey(hKeyToUpdate);
  689. hres = E_FAIL;
  690. break;
  691. }
  692. }
  693. if (REG_SZ == c_wcKEYS[i].c_dwType)
  694. {
  695. // nb of
  696. NumberOfBytesRead = (
  697. ( wcslen((wchar_t*)lpBuffer)
  698. + 1 // for /0
  699. ) * sizeof(wchar_t)
  700. );
  701. };
  702. //
  703. // Key created or key existing
  704. // both can be here (error = break)
  705. //
  706. if (ERROR_SUCCESS != RegSetValueExW(
  707. hKeyToUpdate,
  708. c_wcKEYS[i].c_wcValue,
  709. 0,
  710. c_wcKEYS[i].c_dwType,
  711. (BYTE*)lpBuffer,
  712. NumberOfBytesRead
  713. ))
  714. {
  715. RegCloseKey(hKeyToUpdate);
  716. hres = E_FAIL;
  717. break;
  718. }
  719. RegCloseKey(hKeyToUpdate);
  720. hres = S_OK;
  721. }
  722. CoTaskMemFree(lpBuffer);
  723. }
  724. }
  725. /////////
  726. // Clean
  727. /////////
  728. CoTaskMemFree(completeFile);
  729. return hres;
  730. }
  731. /////////////////////////////////////////////////////////////////////////////
  732. //
  733. // IASExpandString
  734. //
  735. // Expands strings containing %ENV_VARIABLE%
  736. //
  737. // The output string is allocated only when the function succeed
  738. /////////////////////////////////////////////////////////////////////////////
  739. HRESULT
  740. IASExpandString(const wchar_t* pInputString, /*in/out*/ wchar_t** ppOutputString)
  741. {
  742. _ASSERTE(pInputString);
  743. _ASSERTE(pppOutputString);
  744. HRESULT hres;
  745. *ppOutputString = static_cast<wchar_t*>(CoTaskMemAlloc(
  746. SIZELINEMAX
  747. * sizeof(wchar_t)
  748. ));
  749. if ( ! *ppOutputString )
  750. {
  751. hres = E_OUTOFMEMORY;
  752. }
  753. else
  754. {
  755. if ( ExpandEnvironmentStringsForUserW(
  756. NULL,
  757. pInputString,
  758. *ppOutputString,
  759. SIZELINEMAX
  760. )
  761. )
  762. {
  763. hres = S_OK;
  764. }
  765. else
  766. {
  767. CoTaskMemFree(*ppOutputString);
  768. hres = E_FAIL;
  769. }
  770. }
  771. #ifdef DEBUG // DEBUG
  772. wprintf(L"#ExpandString: %s\n", *ppOutputString);
  773. #endif //DEBUG
  774. return hres;
  775. };
  776. /////////////////////////////////////////////////////////////////////////////
  777. //
  778. // DeleteTemporaryFiles()
  779. //
  780. // delete the temporary files if any
  781. //
  782. /////////////////////////////////////////////////////////////////////////////
  783. HRESULT DeleteTemporaryFiles()
  784. {
  785. HRESULT hres;
  786. wchar_t* sz_FileBackup;
  787. CHECK_CALL_HRES (IASExpandString(c_wcFILE_BACKUP,
  788. &sz_FileBackup
  789. )
  790. );
  791. DeleteFile(sz_FileBackup); //return value not checked
  792. CoTaskMemFree(sz_FileBackup);
  793. wchar_t* TempPath;
  794. CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &TempPath));
  795. int c_NbKeys = celems(c_wcKEYS);
  796. for ( int i = 0; i < c_NbKeys; ++i )
  797. {
  798. wstring sFileName(TempPath);
  799. wchar_t buffer[SIZE_LONG_MAX];
  800. _itow(i, buffer, 10); // 10 means base 10
  801. sFileName += buffer;
  802. sFileName += L".txt";
  803. DeleteFile(sFileName.c_str()); //return value not checked
  804. }
  805. CoTaskMemFree(TempPath);
  806. return hres;
  807. }
  808. /////////////////////////////////////////////////////////////////////////////
  809. //
  810. // IASCompress
  811. //
  812. // Wrapper for RtlCompressBuffer
  813. //
  814. /////////////////////////////////////////////////////////////////////////////
  815. HRESULT IASCompress(
  816. PUCHAR pInputBuffer,
  817. ULONG* pulFileSize,
  818. PUCHAR* ppCompressedBuffer
  819. )
  820. {
  821. ULONG size, ignore;
  822. NTSTATUS status = RtlGetCompressionWorkSpaceSize(
  823. COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
  824. &size,
  825. &ignore
  826. );
  827. if (!NT_SUCCESS(status))
  828. {
  829. #ifdef DEBUG
  830. printf("RtlGetCompressionWorkSpaceSize returned 0x%08X.\n", status);
  831. #endif //DEBUG
  832. return E_FAIL;
  833. }
  834. PVOID workSpace;
  835. workSpace = RtlAllocateHeap(
  836. RtlProcessHeap(),
  837. 0,
  838. size
  839. );
  840. if ( !workSpace )
  841. {
  842. return E_OUTOFMEMORY;
  843. }
  844. size = *pulFileSize;
  845. // That's a minimum buffer size that can be used
  846. if ( size < FILE_BUFFER_SIZE )
  847. {
  848. size = FILE_BUFFER_SIZE;
  849. }
  850. *ppCompressedBuffer = static_cast<PUCHAR>(RtlAllocateHeap(
  851. RtlProcessHeap(),
  852. 0,
  853. size
  854. ));
  855. if ( !*ppCompressedBuffer )
  856. {
  857. return E_OUTOFMEMORY;
  858. }
  859. status = RtlCompressBuffer(
  860. COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
  861. pInputBuffer,
  862. size,
  863. *ppCompressedBuffer,
  864. size,
  865. 0,
  866. &size,
  867. workSpace
  868. );
  869. if (!NT_SUCCESS(status))
  870. {
  871. if (STATUS_BUFFER_TOO_SMALL == status)
  872. {
  873. #ifdef DEBUG
  874. printf("STATUS_BUFFER_TOO_SMALL\n");
  875. printf("RtlCompressBuffer returned 0x%08X.\n", status);
  876. #endif //DEBUG
  877. }
  878. else
  879. {
  880. #ifdef DEBUG
  881. printf("RtlCompressBuffer returned 0x%08X.\n", status);
  882. #endif //DEBUG
  883. }
  884. return E_FAIL;
  885. }
  886. *pulFileSize = size;
  887. RtlFreeHeap(
  888. RtlProcessHeap(),
  889. 0,
  890. workSpace
  891. );
  892. return S_OK;
  893. }
  894. /////////////////////////////////////////////////////////////////////////////
  895. //
  896. // IASUnCompress
  897. //
  898. //
  899. /////////////////////////////////////////////////////////////////////////////
  900. HRESULT IASUnCompress(
  901. PUCHAR pInputBuffer,
  902. ULONG* pulFileSize,
  903. PUCHAR* ppDeCompressedBuffer
  904. )
  905. {
  906. ULONG size, ignore;
  907. NTSTATUS status = RtlGetCompressionWorkSpaceSize(
  908. COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
  909. &size,
  910. &ignore
  911. );
  912. if ( !NT_SUCCESS(status) )
  913. {
  914. #ifdef DEBUG
  915. printf("RtlGetCompressionWorkSpaceSize returned 0x%08X.\n", status);
  916. #endif //DEBUG
  917. return E_FAIL;
  918. }
  919. size = *pulFileSize;
  920. if( FILE_BUFFER_SIZE >= size)
  921. {
  922. size = FILE_BUFFER_SIZE;
  923. }
  924. *ppDeCompressedBuffer = static_cast<PUCHAR>(RtlAllocateHeap(
  925. RtlProcessHeap(),
  926. 0,
  927. size * DECOMPRESS_FACTOR
  928. ));
  929. if ( !*ppDeCompressedBuffer )
  930. {
  931. return E_OUTOFMEMORY;
  932. }
  933. ULONG UncompressedSize;
  934. status = RtlDecompressBuffer(
  935. COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
  936. *ppDeCompressedBuffer,
  937. size * DECOMPRESS_FACTOR,
  938. pInputBuffer,
  939. *pulFileSize ,
  940. &UncompressedSize
  941. );
  942. if ( !NT_SUCCESS(status) )
  943. {
  944. #ifdef DEBUG
  945. printf("RtlUnCompressBuffer returned 0x%08X.\n", status);
  946. #endif //DEBUG
  947. switch (status)
  948. {
  949. case STATUS_INVALID_PARAMETER:
  950. #ifdef DEBUG
  951. printf("STATUS_INVALID_PARAMETER");
  952. #endif //DEBUG
  953. break;
  954. case STATUS_BAD_COMPRESSION_BUFFER:
  955. #ifdef DEBUG
  956. printf("STATUS_BAD_COMPRESSION_BUFFER ");
  957. printf("size = %d %d",pulFileSize,UncompressedSize);
  958. #endif //DEBUG
  959. break;
  960. case STATUS_UNSUPPORTED_COMPRESSION:
  961. #ifdef DEBUG
  962. printf("STATUS_UNSUPPORTED_COMPRESSION ");
  963. #endif //DEBUG
  964. break;
  965. }
  966. return E_FAIL;
  967. }
  968. *pulFileSize = UncompressedSize;
  969. return S_OK;
  970. }
  971. /////////////////////////////////////////////////////////////////////////////
  972. //
  973. // IASFileToBase64
  974. //
  975. // Compress then encode to Base64
  976. //
  977. // BSTR by Allocated IASFileToBase64, should be freed by the caller
  978. //
  979. /////////////////////////////////////////////////////////////////////////////
  980. HRESULT
  981. IASFileToBase64(const wchar_t* pFileName, /*out*/ BSTR* pOutputBSTR)
  982. {
  983. _ASSERTE(pFileName);
  984. _ASSERTE(pppOutputString);
  985. HRESULT hres;
  986. HANDLE hFileHandle = CreateFileW(
  987. pFileName,
  988. GENERIC_READ,
  989. FILE_SHARE_READ,
  990. NULL,
  991. OPEN_EXISTING,
  992. FILE_ATTRIBUTE_NORMAL,
  993. NULL
  994. );
  995. if ( hFileHandle == INVALID_HANDLE_VALUE )
  996. {
  997. #ifdef DEBUG
  998. wprintf(L"#filename = %s",pFileName);
  999. wprintf(L"### INVALID_HANDLE_VALUE ###\n");
  1000. #endif //DEBUG
  1001. hres = E_FAIL;
  1002. return hres;
  1003. }
  1004. // safe cast from DWORD to ULONG
  1005. ULONG ulFileSize = (ULONG) GetFileSize(
  1006. hFileHandle, // file for which to get size
  1007. NULL// high-order word of file size
  1008. );
  1009. if (0xFFFFFFFF == ulFileSize)
  1010. {
  1011. #ifdef DEBUG
  1012. wprintf(L"### GetFileSize Failed ###\n");
  1013. #endif //DEBUG
  1014. hres = E_FAIL;
  1015. return hres;
  1016. }
  1017. HANDLE hFileMapping = CreateFileMapping(
  1018. hFileHandle, // handle to file to map
  1019. NULL, // optional security attributes
  1020. PAGE_READONLY, // protection for mapping object
  1021. 0, // high-order 32 bits of object size
  1022. 0, // low-order 32 bits of object size
  1023. NULL // name of file-mapping object
  1024. );
  1025. if (NULL == hFileMapping)
  1026. {
  1027. #ifdef DEBUG
  1028. wprintf(L"### CreateFileMapping Failed ###\n");
  1029. #endif //DEBUG
  1030. hres = E_FAIL;
  1031. return hres;
  1032. }
  1033. LPVOID pMemoryFile = MapViewOfFile(
  1034. hFileMapping, // file-mapping object to map into
  1035. // address space
  1036. FILE_MAP_READ, // access mode
  1037. 0, // high-order 32 bits of file offset
  1038. 0, // low-order 32 bits of file offset
  1039. 0 // number of bytes to map
  1040. );
  1041. if (NULL == pMemoryFile)
  1042. {
  1043. #ifdef DEBUG
  1044. wprintf(L"### MapViewOfFile Failed ###\n");
  1045. #endif //DEBUG
  1046. hres = E_FAIL;
  1047. return hres;
  1048. }
  1049. /////////////////////////////
  1050. // NOW compress
  1051. /////////////////////////////
  1052. wchar_t* pCompressedBuffer;
  1053. CHECK_CALL_HRES (IASCompress((PUCHAR) pMemoryFile,
  1054. /*IN OUT*/(ULONG *) &ulFileSize,
  1055. /*IN OUT*/(PUCHAR*) &pCompressedBuffer));
  1056. /////////////////////
  1057. // Encode to Base64
  1058. /////////////////////
  1059. CHECK_CALL_HRES (ToBase64(
  1060. pCompressedBuffer,
  1061. (ULONG) ulFileSize,
  1062. pOutputBSTR
  1063. )
  1064. );
  1065. /////////////////////////////
  1066. // Clean
  1067. /////////////////////////////
  1068. RtlFreeHeap(
  1069. RtlProcessHeap(),
  1070. 0,
  1071. pCompressedBuffer
  1072. );
  1073. BOOL bResult = UnmapViewOfFile(
  1074. pMemoryFile// address where mapped view begins
  1075. );
  1076. if (FALSE == bResult)
  1077. {
  1078. #ifdef DEBUG
  1079. wprintf(L"### UnmapViewOfFile Failed ###\n");
  1080. #endif //DEBUG
  1081. hres = E_FAIL;
  1082. }
  1083. CloseHandle(hFileMapping);
  1084. CloseHandle(hFileHandle);
  1085. return hres;
  1086. }
  1087. /////////////////////////////////////////////////////////////////////////////
  1088. //
  1089. // IASDumpConfig
  1090. //
  1091. // Dump the configuration to some temporary files, then indidually
  1092. // compress then encode them.
  1093. // one big string is created from those multiple Base64 strings.
  1094. //
  1095. // Remarks: IASDumpConfig does a malloc and allocates memory for
  1096. // *ppDumpString. The calling function will have to free that memory
  1097. //
  1098. /////////////////////////////////////////////////////////////////////////////
  1099. HRESULT
  1100. IASDumpConfig(/*inout*/ wchar_t **ppDumpString, /*inout*/ ULONG *ulSize)
  1101. {
  1102. _ASSERTE(ppDumpString);
  1103. _ASSERTE(ulSize);
  1104. HRESULT hres;
  1105. ///////////////////////////////////////
  1106. // delete the temporary files if any
  1107. ///////////////////////////////////////
  1108. CHECK_CALL_HRES (DeleteTemporaryFiles());
  1109. ////////////////////////////////////////////////////
  1110. // Save the Registry keys. that creates many files
  1111. ////////////////////////////////////////////////////
  1112. CHECK_CALL_HRES (IASSaveRegKeys());
  1113. //////////////////////
  1114. // connect to the DB
  1115. //////////////////////
  1116. wchar_t* sz_DBPath;
  1117. CHECK_CALL_HRES (IASExpandString(c_wcIAS_MDB_FILE_NAME, &sz_DBPath));
  1118. CComPtr<IIASNetshJetHelper> JetHelper;
  1119. CHECK_CALL_HRES (CoCreateInstance(
  1120. __uuidof(CIASNetshJetHelper),
  1121. NULL,
  1122. CLSCTX_SERVER,
  1123. __uuidof(IIASNetshJetHelper),
  1124. (PVOID*) &JetHelper
  1125. ));
  1126. CComBSTR DBPath(sz_DBPath);
  1127. if ( !DBPath ) { return E_OUTOFMEMORY; }
  1128. CHECK_CALL_HRES (JetHelper->OpenJetDatabase(DBPath, TRUE));
  1129. //////////////////////////////////////
  1130. // Create a new DB named "Backup.mdb"
  1131. //////////////////////////////////////
  1132. wchar_t* sz_FileBackup;
  1133. CHECK_CALL_HRES (IASExpandString(c_wcFILE_BACKUP,
  1134. &sz_FileBackup
  1135. )
  1136. );
  1137. CComBSTR BackupDb(sz_FileBackup);
  1138. if ( !BackupDb ) { return E_OUTOFMEMORY; }
  1139. CHECK_CALL_HRES (JetHelper->CreateJetDatabase(BackupDb));
  1140. //////////////////////////////////////////////////////////
  1141. // exec the sql statements (to export)
  1142. // the content into the temp database
  1143. //////////////////////////////////////////////////////////
  1144. wchar_t* sz_SelectProperties;
  1145. CHECK_CALL_HRES (IASExpandString(c_wcSELECT_PROPERTIES_INTO,
  1146. &sz_SelectProperties
  1147. )
  1148. );
  1149. CComBSTR SelectProperties(sz_SelectProperties);
  1150. if ( !SelectProperties ) { return E_OUTOFMEMORY; }
  1151. CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectProperties));
  1152. wchar_t* sz_SelectObjects;
  1153. CHECK_CALL_HRES (IASExpandString(c_wcSELECT_OBJECTS_INTO,
  1154. &sz_SelectObjects
  1155. )
  1156. );
  1157. CComBSTR SelectObjects(sz_SelectObjects);
  1158. if ( !SelectObjects ) { return E_OUTOFMEMORY; }
  1159. CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectObjects));
  1160. wchar_t* sz_SelectVersion;
  1161. CHECK_CALL_HRES (IASExpandString(c_wcSELECT_VERSION_INTO,
  1162. &sz_SelectVersion
  1163. )
  1164. );
  1165. CComBSTR SelectVersion(sz_SelectVersion);
  1166. if ( !SelectVersion ) { return E_OUTOFMEMORY; }
  1167. CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectVersion));
  1168. /////////////////////////////////////////////
  1169. // transform the file into Base64 BSTR
  1170. /////////////////////////////////////////////
  1171. BSTR FileBackupBSTR;
  1172. CHECK_CALL_HRES (IASFileToBase64(
  1173. sz_FileBackup,
  1174. &FileBackupBSTR
  1175. )
  1176. );
  1177. int NumberOfKeyFiles = celems(c_wcKEYS);
  1178. BSTR pFileKeys[celems(c_wcKEYS)];
  1179. wchar_t* sz_FileRegistry;
  1180. CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE,
  1181. &sz_FileRegistry
  1182. )
  1183. );
  1184. for ( int i = 0; i < NumberOfKeyFiles; ++i )
  1185. {
  1186. wstring sFileName(sz_FileRegistry);
  1187. wchar_t buffer[SIZE_LONG_MAX];
  1188. _itow(i, buffer, 10); // 10 means base 10
  1189. sFileName += buffer;
  1190. sFileName += L".txt";
  1191. CHECK_CALL_HRES (IASFileToBase64(
  1192. sFileName.c_str(),
  1193. &pFileKeys[i]
  1194. )
  1195. );
  1196. }
  1197. CoTaskMemFree(sz_FileRegistry);
  1198. ///////////////////////////////////////////////
  1199. // alloc the memory for full the Base64 string
  1200. ///////////////////////////////////////////////
  1201. *ulSize = SysStringByteLen(FileBackupBSTR)
  1202. + EXTRA_CHAR_SPACE;
  1203. for ( int j = 0; j < NumberOfKeyFiles; ++j )
  1204. {
  1205. *ulSize += SysStringByteLen(pFileKeys[j]);
  1206. *ulSize += 2; // extra characters
  1207. }
  1208. *ppDumpString = (wchar_t *) calloc(
  1209. *ulSize ,
  1210. sizeof(wchar_t)
  1211. );
  1212. //////////////////////////////////////////////////
  1213. // copy the different strings into one big string
  1214. //////////////////////////////////////////////////
  1215. if (*ppDumpString)
  1216. {
  1217. wcsncpy(
  1218. (wchar_t*) *ppDumpString,
  1219. (wchar_t*) FileBackupBSTR,
  1220. SysStringLen(FileBackupBSTR)
  1221. );
  1222. for ( int k = 0; k < NumberOfKeyFiles; ++k )
  1223. {
  1224. wcscat(
  1225. (wchar_t*) *ppDumpString,
  1226. L"*\\\n"
  1227. );
  1228. wcsncat(
  1229. (wchar_t*) *ppDumpString,
  1230. (wchar_t*) pFileKeys[k],
  1231. SysStringLen(pFileKeys[k])
  1232. );
  1233. }
  1234. wcscat(
  1235. (wchar_t*) *ppDumpString,
  1236. L"QWER * QWER\\\n"
  1237. );
  1238. *ulSize = wcslen(*ppDumpString);
  1239. }
  1240. else
  1241. {
  1242. hres = E_OUTOFMEMORY;
  1243. #ifdef DEBUG
  1244. wprintf(L"### calloc failed ###\n");
  1245. #endif //DEBUG
  1246. }
  1247. ///////////////////////////////////////
  1248. // delete the temporary files if any
  1249. ///////////////////////////////////////
  1250. CHECK_CALL_HRES (DeleteTemporaryFiles());
  1251. /////////////////////////////////////////////
  1252. // Clean
  1253. /////////////////////////////////////////////
  1254. for ( int k = 0; k < NumberOfKeyFiles; ++k )
  1255. {
  1256. SysFreeString(pFileKeys[k]);
  1257. }
  1258. CoTaskMemFree(sz_SelectVersion);
  1259. CoTaskMemFree(sz_SelectProperties);
  1260. CoTaskMemFree(sz_SelectObjects);
  1261. CoTaskMemFree(sz_FileBackup);
  1262. CoTaskMemFree(sz_DBPath);
  1263. SysFreeString(FileBackupBSTR);
  1264. CHECK_CALL_HRES (JetHelper->CloseJetDatabase());
  1265. return hres;
  1266. }
  1267. /////////////////////////////////////////////////////////////////////////////
  1268. //
  1269. // IASSaveToFile
  1270. //
  1271. // Remark: if a new table has to be saved, an "entry" for that should be
  1272. // created in that function to deal with the filemname
  1273. //
  1274. /////////////////////////////////////////////////////////////////////////////
  1275. HRESULT IASSaveToFile(
  1276. /* in */ int Index,
  1277. /* in */ wchar_t* pContent,
  1278. DWORD lSize = 0
  1279. )
  1280. {
  1281. HRESULT hres;
  1282. wstring sFileName;
  1283. switch (Index)
  1284. {
  1285. case BACKUP_NB:
  1286. {
  1287. wchar_t* sz_FileBackup;
  1288. CHECK_CALL_HRES (IASExpandString(c_wcIAS_OLD,
  1289. &sz_FileBackup
  1290. )
  1291. );
  1292. sFileName = sz_FileBackup;
  1293. CoTaskMemFree(sz_FileBackup);
  1294. break;
  1295. }
  1296. ///////////
  1297. // binary
  1298. ///////////
  1299. default:
  1300. {
  1301. ///////////////////////////////////
  1302. // i + BINARY_NB is the parameter
  1303. ///////////////////////////////////
  1304. wchar_t* sz_FileRegistry;
  1305. CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE,
  1306. &sz_FileRegistry
  1307. )
  1308. );
  1309. sFileName = sz_FileRegistry;
  1310. wchar_t buffer[SIZE_LONG_MAX];
  1311. _itow(Index - BINARY_NB, buffer, 10); // 10 means base 10
  1312. sFileName += buffer;
  1313. sFileName += L".txt";
  1314. CoTaskMemFree(sz_FileRegistry);
  1315. break;
  1316. }
  1317. }
  1318. HANDLE hFile = CreateFileW(
  1319. sFileName.c_str(),
  1320. GENERIC_WRITE,
  1321. FILE_SHARE_WRITE | FILE_SHARE_READ,
  1322. NULL,
  1323. CREATE_ALWAYS,
  1324. FILE_ATTRIBUTE_NORMAL,
  1325. NULL
  1326. );
  1327. if (INVALID_HANDLE_VALUE == hFile)
  1328. {
  1329. hres = E_FAIL;
  1330. }
  1331. else
  1332. {
  1333. DWORD NumberOfBytesWritten;
  1334. BOOL bResult = WriteFile(
  1335. hFile,
  1336. (LPVOID) pContent,
  1337. lSize,
  1338. &NumberOfBytesWritten,
  1339. NULL
  1340. );
  1341. if (bResult)
  1342. {
  1343. hres = S_OK;
  1344. }
  1345. else
  1346. {
  1347. hres = E_FAIL;
  1348. }
  1349. CloseHandle(hFile);
  1350. }
  1351. return hres;
  1352. }
  1353. /////////////////////////////////////////////////////////////////////////////
  1354. // IASRestoreConfig
  1355. //
  1356. // Clean the DB first, then insert back everything.
  1357. /////////////////////////////////////////////////////////////////////////////
  1358. HRESULT IASRestoreConfig(
  1359. /*in*/ const wchar_t *pRestoreString,
  1360. /*in*/ IAS_SHOW_TOKEN_LIST configType
  1361. )
  1362. {
  1363. _ASSERTE(pRestoreString);
  1364. bool bCoInitialized = false;
  1365. HRESULT hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1366. if (FAILED(hres))
  1367. {
  1368. if (RPC_E_CHANGED_MODE == hres)
  1369. {
  1370. hres = S_OK;
  1371. }
  1372. else
  1373. {
  1374. return hres;
  1375. }
  1376. }
  1377. else
  1378. {
  1379. bCoInitialized = true;
  1380. }
  1381. BSTR bstr = NULL;
  1382. do
  1383. {
  1384. ///////////////////////////////////////
  1385. // delete the temporary files if any
  1386. ///////////////////////////////////////
  1387. CHECK_CALL_HRES_BREAK (DeleteTemporaryFiles());
  1388. CComPtr<IIASNetshJetHelper> JetHelper;
  1389. CHECK_CALL_HRES_BREAK (CoCreateInstance(
  1390. __uuidof(CIASNetshJetHelper),
  1391. NULL,
  1392. CLSCTX_SERVER,
  1393. __uuidof(IIASNetshJetHelper),
  1394. (PVOID*) &JetHelper
  1395. ));
  1396. bstr = SysAllocStringLen(
  1397. pRestoreString,
  1398. wcslen(pRestoreString) + 2
  1399. );
  1400. if (bstr == NULL)
  1401. {
  1402. #ifdef DEBUG
  1403. wprintf(L"### IASRestoreConfig->SysAllocStringLen failed\n");
  1404. #endif //DEBUG
  1405. return E_OUTOFMEMORY;
  1406. }
  1407. int RealNumberOfFiles = MAX_FILES + celems(c_wcKEYS);
  1408. for ( int i = 0; i < RealNumberOfFiles; ++i )
  1409. {
  1410. BLOB lBlob;
  1411. lBlob.cbSize = 0;
  1412. lBlob.pBlobData = NULL;
  1413. // split the files and registry info
  1414. // uncompress (in memory ?)
  1415. CHECK_CALL_HRES_BREAK (FromBase64(bstr, &lBlob, i));
  1416. ULONG ulSize = lBlob.cbSize;
  1417. PUCHAR pDeCompressedBuffer;
  1418. if (ulSize == 0)
  1419. {
  1420. // file with less sections than expected
  1421. // for instance before the number of reg keys increased
  1422. // ignore
  1423. continue;
  1424. }
  1425. ////////////////////////////////////
  1426. // decode and decompress the base64
  1427. ////////////////////////////////////
  1428. CHECK_CALL_HRES_BREAK (IASUnCompress(
  1429. lBlob.pBlobData,
  1430. &ulSize,
  1431. &pDeCompressedBuffer
  1432. ))
  1433. if ( i >= MAX_FILES )
  1434. {
  1435. /////////////////////////////////////
  1436. // Binary; i + BINARY_NB used here
  1437. /////////////////////////////////////
  1438. IASSaveToFile(
  1439. i - MAX_FILES + BINARY_NB,
  1440. (wchar_t*)pDeCompressedBuffer,
  1441. (DWORD) ulSize
  1442. );
  1443. }
  1444. else
  1445. {
  1446. IASSaveToFile(
  1447. i,
  1448. (wchar_t*)pDeCompressedBuffer,
  1449. (DWORD) ulSize
  1450. );
  1451. }
  1452. ////////////
  1453. // Clean
  1454. ////////////
  1455. RtlFreeHeap(RtlProcessHeap(), 0, pDeCompressedBuffer);
  1456. CoTaskMemFree(lBlob.pBlobData);
  1457. }
  1458. ///////////////////////////////////////////////////
  1459. // Now Upgrade the database (That's transactional)
  1460. ///////////////////////////////////////////////////
  1461. hres = JetHelper->MigrateOrUpgradeDatabase(configType);
  1462. if ( SUCCEEDED(hres) )
  1463. {
  1464. #ifdef DEBUG
  1465. wprintf(L"### IASRestoreConfig->DB stuff successful\n");
  1466. #endif //DEBUG
  1467. ////////////////////////////////////////////////////////
  1468. // Now restore the registry.
  1469. ////////////////////////////////////////////////////////
  1470. hres = IASRestoreRegKeys(configType);
  1471. if ( FAILED(hres) )
  1472. {
  1473. #ifdef DEBUG
  1474. wprintf(L"### IASRestoreConfig->restore reg keys failed\n");
  1475. #endif //DEBUG
  1476. }
  1477. }
  1478. // delete the temporary files
  1479. DeleteTemporaryFiles(); // do not check the result
  1480. } while (false);
  1481. SysFreeString(bstr);
  1482. if (bCoInitialized)
  1483. {
  1484. CoUninitialize();
  1485. }
  1486. return hres;
  1487. }