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

827 lines
23 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1997.
  5. //
  6. // File: clspsht.cpp
  7. //
  8. // Contents: Implements class CClsidPropertySheet
  9. //
  10. // Classes:
  11. //
  12. // Methods: CClsidPropertySheet::CClsidPropertySheet
  13. // CClsidPropertySheet::~CClsidPropertySheet
  14. // CClsidPropertySheet::InitData
  15. // CClsidPropertySheet::OnNcCreate
  16. // CClsidPropertySheet::ValidateAndUpdate
  17. // CClsidPropertySheet::OnCommand
  18. // CClsidPropertySheet::LookAtCLSIDs
  19. // CClsidPropertySheet::ChangeCLSIDInfo
  20. //
  21. // History: 23-Apr-96 BruceMa Created.
  22. //
  23. //----------------------------------------------------------------------
  24. #include "stdafx.h"
  25. #include "resource.h"
  26. #include "clspsht.h"
  27. #include "datapkt.h"
  28. #if !defined(STANDALONE_BUILD)
  29. extern "C"
  30. {
  31. #include <getuser.h>
  32. }
  33. #endif
  34. #include "util.h"
  35. #include "newsrvr.h"
  36. #if !defined(STANDALONE_BUILD)
  37. extern "C"
  38. {
  39. #include <sedapi.h>
  40. #include <ntlsa.h>
  41. }
  42. #endif
  43. #ifdef _DEBUG
  44. #define new DEBUG_NEW
  45. #undef THIS_FILE
  46. static char BASED_CODE THIS_FILE[] = __FILE__;
  47. #endif
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CClsidPropertySheet
  50. IMPLEMENT_DYNAMIC(CClsidPropertySheet, CPropertySheet)
  51. CClsidPropertySheet::CClsidPropertySheet(CWnd* pParentWnd)
  52. : CPropertySheet(IDS_PROPSHT_CAPTION1, pParentWnd)
  53. {
  54. }
  55. CClsidPropertySheet::~CClsidPropertySheet()
  56. {
  57. }
  58. BEGIN_MESSAGE_MAP(CClsidPropertySheet, CPropertySheet)
  59. //{{AFX_MSG_MAP(CClsidPropertySheet)
  60. ON_WM_NCCREATE()
  61. //}}AFX_MSG_MAP
  62. END_MESSAGE_MAP()
  63. CClsidPropertySheet::InitData(
  64. CString szAppName,
  65. HKEY hkAppID,
  66. HKEY * rghkCLSID,
  67. unsigned cCLSIDs)
  68. {
  69. m_szAppName = szAppName;
  70. m_hkAppID = hkAppID;
  71. m_rghkCLSID = rghkCLSID;
  72. m_cCLSIDs = cCLSIDs;
  73. // Save the appid key, the table of clsid keys and the application
  74. // title globally so the property pages can access them
  75. // it
  76. g_hAppid = hkAppID;
  77. g_rghkCLSID = rghkCLSID;
  78. g_cCLSIDs = cCLSIDs;
  79. g_szAppTitle = (TCHAR *) LPCTSTR(szAppName);
  80. m_Page2.m_fRemote = FALSE;
  81. m_Page4.m_fService = FALSE;
  82. m_Page2.m_fCanBeLocal = FALSE;
  83. m_Page2.m_fLocal = FALSE;
  84. m_Page1.m_fSurrogate = FALSE;
  85. if (!LookAtCLSIDs())
  86. {
  87. return FALSE;
  88. }
  89. TCHAR szBuffer[MAX_PATH];
  90. DWORD dwSize;
  91. long lErr;
  92. dwSize = sizeof(szBuffer);
  93. lErr = RegQueryValueEx(
  94. m_hkAppID,
  95. TEXT("LocalService"),
  96. NULL,
  97. NULL,
  98. (BYTE *)szBuffer,
  99. &dwSize);
  100. if (lErr == ERROR_SUCCESS)
  101. {
  102. m_Page1.m_szServerPath = szBuffer;
  103. m_Page4.m_fService = TRUE;
  104. m_Page2.m_fCanBeLocal = TRUE;
  105. m_Page2.m_fLocal = TRUE;
  106. }
  107. else
  108. {
  109. dwSize = sizeof(szBuffer);
  110. lErr = RegQueryValueEx(
  111. m_hkAppID,
  112. TEXT("_LocalService"),
  113. NULL,
  114. NULL,
  115. (BYTE *)szBuffer,
  116. &dwSize);
  117. if (lErr == ERROR_SUCCESS)
  118. {
  119. m_Page1.m_szServerPath = szBuffer;
  120. m_Page4.m_fService = TRUE;
  121. m_Page2.m_fCanBeLocal = TRUE;
  122. }
  123. }
  124. dwSize = sizeof(szBuffer);
  125. if (!m_Page2.m_fLocal)
  126. {
  127. lErr = RegQueryValueEx(
  128. m_hkAppID,
  129. TEXT("DllSurrogate"),
  130. NULL,
  131. NULL,
  132. (BYTE *)szBuffer,
  133. &dwSize);
  134. if (lErr == ERROR_SUCCESS)
  135. {
  136. if (szBuffer[0])
  137. m_Page1.m_szServerPath = szBuffer;
  138. else
  139. m_Page1.m_szServerPath.LoadString(IDS_DEFAULT);
  140. m_Page1.m_fSurrogate = TRUE;
  141. }
  142. }
  143. dwSize = sizeof(szBuffer);
  144. lErr = RegQueryValueEx(
  145. m_hkAppID,
  146. TEXT("RemoteServerName"),
  147. NULL,
  148. NULL,
  149. (BYTE *)szBuffer,
  150. &dwSize);
  151. if (lErr == ERROR_SUCCESS)
  152. {
  153. m_Page1.m_szComputerName = szBuffer;
  154. m_Page2.m_szComputerName = szBuffer;
  155. m_Page2.m_fRemote = TRUE;
  156. }
  157. m_Page2.m_fAtStorage = FALSE;
  158. dwSize = sizeof(szBuffer);
  159. lErr = RegQueryValueEx(
  160. m_hkAppID,
  161. TEXT("ActivateAtStorage"),
  162. NULL,
  163. NULL,
  164. (BYTE *)szBuffer,
  165. &dwSize);
  166. if (lErr == ERROR_SUCCESS)
  167. {
  168. if (szBuffer[0] == L'Y' || szBuffer[0] == L'y')
  169. {
  170. // m_Page2.m_fRemote = TRUE;
  171. m_Page2.m_fAtStorage = TRUE;
  172. }
  173. }
  174. dwSize = sizeof(szBuffer);
  175. lErr = RegQueryValueEx(
  176. m_hkAppID,
  177. TEXT("RunAs"),
  178. NULL,
  179. NULL,
  180. (BYTE *)szBuffer,
  181. &dwSize);
  182. if (lErr == ERROR_SUCCESS)
  183. {
  184. // If the RunAs name is empty, jam in something
  185. if (szBuffer[0] == TEXT('\0'))
  186. {
  187. _tcscpy(szBuffer, TEXT("<domain>\\<user>"));
  188. }
  189. if (0 == _tcsicmp(szBuffer, TEXT("Interactive User")))
  190. {
  191. m_Page4.m_iIdentity = 0;
  192. }
  193. else
  194. {
  195. m_Page4.m_iIdentity = 2;
  196. m_Page4.m_szUserName = szBuffer;
  197. // Extract password from the Lsa private database
  198. g_util.RetrieveUserPassword(g_szAppid , m_Page4.m_szPassword);
  199. m_Page4.m_szConfirmPassword = m_Page4.m_szPassword;
  200. }
  201. }
  202. else
  203. {
  204. if (m_Page4.m_fService)
  205. {
  206. m_Page4.m_iIdentity = 3;
  207. }
  208. else
  209. {
  210. m_Page4.m_iIdentity = 1;
  211. }
  212. }
  213. m_Page1.m_szServerName = m_szAppName;
  214. if (!m_Page1.m_fSurrogate)
  215. {
  216. if (m_Page2.m_fCanBeLocal)
  217. {
  218. if (m_Page4.m_fService)
  219. m_Page1.m_iServerType = SERVICE;
  220. else
  221. m_Page1.m_iServerType = LOCALEXE;
  222. if (m_Page2.m_fRemote)
  223. m_Page1.m_iServerType += 3;
  224. }
  225. else
  226. m_Page1.m_iServerType = PURE_REMOTE;
  227. }
  228. else
  229. {
  230. m_Page1.m_iServerType = SURROGATE;
  231. }
  232. // Set the title
  233. SetTitle((const TCHAR *) m_szAppName, PSH_PROPTITLE);
  234. m_Page1.m_szServerName = m_szAppName;
  235. // TODO: If there are running instances, then make IDC_RUNNING,
  236. // IDC_LIST2, IDC_BUTTON1, IDC_BUTTON2, and IDC_BUTTON3 visible
  237. // and fill in IDC_LIST2 on page 1.
  238. m_Page2.m_pPage1 = &m_Page1;
  239. // Fetch RunAs key, LaunchPermission, AccessPermission and
  240. // ConfigurationPermission
  241. int err;
  242. DWORD dwType;
  243. BYTE bValue[16];
  244. BYTE *pbValue = NULL;
  245. ULONG ulSize = 1;
  246. m_Page3.m_iAccess = 0;
  247. m_Page3.m_iLaunch = 0;
  248. m_Page3.m_iConfig = 0;
  249. // "AccessPermission"
  250. // Note: We always expect to get ERROR_MORE_DATA
  251. err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0,
  252. &dwType, bValue, &ulSize);
  253. if (err == ERROR_MORE_DATA)
  254. {
  255. pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize);
  256. if (pbValue == NULL)
  257. {
  258. return FALSE;
  259. }
  260. err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0,
  261. &dwType, pbValue, &ulSize);
  262. }
  263. if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
  264. {
  265. m_Page3.m_iAccess = 1;
  266. g_virtreg.NewRegSingleACL(g_hAppid,
  267. NULL,
  268. TEXT("AccessPermission"),
  269. (SECURITY_DESCRIPTOR *) pbValue,
  270. TRUE, // Already in self-relative form
  271. &m_Page3.m_iAccessIndex);
  272. CDataPacket *pCdb = g_virtreg.GetAt(m_Page3.m_iAccessIndex);
  273. pCdb->SetModified(FALSE);
  274. }
  275. GlobalFree(pbValue);
  276. pbValue = NULL;
  277. // "LaunchPermission"
  278. // Note: We always expect to get ERROR_MORE_DATA
  279. ulSize = 1;
  280. pbValue = NULL;
  281. err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0,
  282. &dwType, bValue, &ulSize);
  283. if (err == ERROR_MORE_DATA)
  284. {
  285. pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize);
  286. if (pbValue == NULL)
  287. {
  288. return FALSE;
  289. }
  290. err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0,
  291. &dwType, pbValue, &ulSize);
  292. }
  293. if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
  294. {
  295. m_Page3.m_iLaunch = 1;
  296. g_virtreg.NewRegSingleACL(g_hAppid,
  297. NULL,
  298. TEXT("LaunchPermission"),
  299. (SECURITY_DESCRIPTOR *) pbValue,
  300. TRUE, // Already in self-relative form
  301. &m_Page3.m_iLaunchIndex);
  302. CDataPacket * pCdb = g_virtreg.GetAt(m_Page3.m_iLaunchIndex);
  303. pCdb->SetModified(FALSE);
  304. }
  305. GlobalFree(pbValue);
  306. pbValue = NULL;
  307. // "ConfigurationPermission"
  308. // Fetch the security descriptor on this AppID
  309. // Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
  310. ulSize = 1;
  311. err = RegGetKeySecurity(g_hAppid,
  312. OWNER_SECURITY_INFORMATION |
  313. GROUP_SECURITY_INFORMATION |
  314. DACL_SECURITY_INFORMATION,
  315. pbValue,
  316. &ulSize);
  317. if (err == ERROR_INSUFFICIENT_BUFFER)
  318. {
  319. pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize);
  320. if (pbValue == NULL)
  321. {
  322. return FALSE;
  323. }
  324. err = RegGetKeySecurity(g_hAppid,
  325. OWNER_SECURITY_INFORMATION |
  326. GROUP_SECURITY_INFORMATION |
  327. DACL_SECURITY_INFORMATION,
  328. pbValue,
  329. &ulSize);
  330. }
  331. // Fetch the current security descriptor on HKEY_CLASSES_ROOT
  332. // Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
  333. BYTE *pbValue2 = NULL;
  334. ulSize = 1;
  335. pbValue2 = NULL;
  336. err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
  337. OWNER_SECURITY_INFORMATION |
  338. GROUP_SECURITY_INFORMATION |
  339. DACL_SECURITY_INFORMATION,
  340. pbValue2,
  341. &ulSize);
  342. if (err == ERROR_INSUFFICIENT_BUFFER)
  343. {
  344. pbValue2 = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize);
  345. if (pbValue2 == NULL)
  346. {
  347. return FALSE;
  348. }
  349. err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
  350. OWNER_SECURITY_INFORMATION |
  351. GROUP_SECURITY_INFORMATION |
  352. DACL_SECURITY_INFORMATION,
  353. pbValue2,
  354. &ulSize);
  355. }
  356. // Now compare them. If they differ then this AppId uses custom
  357. // configuration permissions
  358. if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
  359. {
  360. if (!g_util.CompareSDs((PSrSecurityDescriptor) pbValue,
  361. (PSrSecurityDescriptor) pbValue2))
  362. {
  363. err = g_virtreg.NewRegKeyACL(g_hAppid,
  364. rghkCLSID,
  365. cCLSIDs,
  366. g_szAppTitle,
  367. (SECURITY_DESCRIPTOR *) pbValue,
  368. (SECURITY_DESCRIPTOR *) pbValue,
  369. TRUE,
  370. &m_Page3.m_iConfigurationIndex);
  371. CDataPacket * pCdb = g_virtreg.GetAt(m_Page3.m_iConfigurationIndex);
  372. pCdb->SetModified(FALSE);
  373. m_Page3.m_iConfig = 1;
  374. }
  375. }
  376. GlobalFree(pbValue);
  377. GlobalFree(pbValue2);
  378. // Add all of the property pages here. Note that
  379. // the order that they appear in here will be
  380. // the order they appear in on screen. By default,
  381. // the first page of the set is the active one.
  382. // One way to make a different property page the
  383. // active one is to call SetActivePage().
  384. AddPage(&m_Page1);
  385. if (m_Page1.m_iServerType != SURROGATE)
  386. {
  387. AddPage(&m_Page2);
  388. }
  389. if (m_Page2.m_fCanBeLocal || m_Page1.m_fSurrogate)
  390. {
  391. AddPage(&m_Page3);
  392. AddPage(&m_Page4);
  393. }
  394. // add the property page for endpoint options
  395. AddPage(&m_Page5);
  396. m_Page5.InitData(szAppName, hkAppID);
  397. return TRUE;
  398. }
  399. /////////////////////////////////////////////////////////////////////////////
  400. // CClsidPropertySheet message handlers
  401. BOOL CClsidPropertySheet::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
  402. {
  403. if (!CPropertySheet::OnNcCreate(lpCreateStruct))
  404. return FALSE;
  405. ModifyStyleEx(0, WS_EX_CONTEXTHELP);
  406. return TRUE;
  407. }
  408. BOOL CClsidPropertySheet::ValidateAndUpdate(void)
  409. {
  410. // Call update data on all initialized pages
  411. // to make sure that their private member variables are correct.
  412. long lErr;
  413. BOOL fReturn = UpdateData(TRUE);
  414. if (fReturn && m_Page1.m_hWnd)
  415. fReturn = m_Page1.ValidateChanges();
  416. if (fReturn && m_Page2.m_hWnd)
  417. fReturn = m_Page2.ValidateChanges();
  418. if (fReturn && m_Page3.m_hWnd)
  419. fReturn = m_Page3.ValidateChanges();
  420. if (fReturn && m_Page4.m_hWnd)
  421. fReturn = m_Page4.ValidateChanges();
  422. if (fReturn && m_Page5.m_hWnd)
  423. fReturn = m_Page5.ValidateChanges();
  424. if (!fReturn)
  425. return FALSE;
  426. m_Page1.UpdateChanges(m_hkAppID);
  427. m_Page2.UpdateChanges(m_hkAppID);
  428. m_Page3.UpdateChanges(m_hkAppID);
  429. m_Page4.UpdateChanges(m_hkAppID);
  430. m_Page5.UpdateChanges(m_hkAppID);
  431. ////////////////////////////////////////////////////////////////////
  432. // Persist cross page data
  433. if (m_Page4.m_fService)
  434. {
  435. if (m_Page2.m_fLocal)
  436. {
  437. BOOL fOk;
  438. // Write the LocalService value to the registry
  439. lErr = RegSetValueEx(
  440. m_hkAppID,
  441. TEXT("LocalService"),
  442. 0,
  443. REG_SZ,
  444. (BYTE *)(LPCTSTR)m_Page1.m_szServerPath,
  445. (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR));
  446. lErr = RegDeleteValue(
  447. m_hkAppID,
  448. TEXT("_LocalService"));
  449. // Persist information to the service manager database
  450. if (m_Page4.m_iIdentity == 3)
  451. {
  452. fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath,
  453. TEXT("LocalSystem"),
  454. TEXT(""),
  455. (LPCTSTR) m_Page1.m_szServerName);
  456. }
  457. else
  458. {
  459. fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath,
  460. (LPCTSTR) m_Page4.m_szUserName,
  461. (LPCTSTR) m_Page4.m_szPassword,
  462. (LPCTSTR) m_Page1.m_szServerName);
  463. }
  464. if (!fOk)
  465. {
  466. return FALSE;
  467. }
  468. }
  469. else
  470. {
  471. lErr = RegSetValueEx(
  472. m_hkAppID,
  473. TEXT("_LocalService"),
  474. 0,
  475. REG_SZ,
  476. (BYTE *)(LPCTSTR)m_Page1.m_szServerPath,
  477. (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR));
  478. lErr = RegDeleteValue(
  479. m_hkAppID,
  480. TEXT("LocalService"));
  481. }
  482. }
  483. return ChangeCLSIDInfo(m_Page2.m_fLocal);
  484. }
  485. BOOL CClsidPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
  486. {
  487. switch (LOWORD(wParam))
  488. {
  489. case IDOK:
  490. case ID_APPLY_NOW:
  491. if (!ValidateAndUpdate())
  492. return TRUE;
  493. break;
  494. }
  495. return CPropertySheet::OnCommand(wParam, lParam);
  496. }
  497. BOOL CClsidPropertySheet::LookAtCLSIDs(void)
  498. {
  499. BOOL fFoundLocalServer = FALSE;
  500. TCHAR szBuffer[MAX_PATH];
  501. DWORD dwSize;
  502. HKEY hKey;
  503. long lErr;
  504. unsigned n = 0;
  505. while (n < m_cCLSIDs && !fFoundLocalServer)
  506. {
  507. lErr = RegOpenKeyEx(
  508. m_rghkCLSID[n],
  509. TEXT("LocalServer32"),
  510. 0,
  511. KEY_ALL_ACCESS,
  512. &hKey);
  513. if (lErr == ERROR_SUCCESS)
  514. {
  515. dwSize = sizeof(szBuffer);
  516. lErr = RegQueryValueEx(
  517. hKey,
  518. TEXT(""),
  519. NULL,
  520. NULL,
  521. (BYTE *)szBuffer,
  522. &dwSize);
  523. if (lErr == ERROR_SUCCESS)
  524. {
  525. m_Page1.m_szServerPath = szBuffer;
  526. m_Page2.m_fLocal = TRUE;
  527. m_Page2.m_fCanBeLocal = TRUE;
  528. fFoundLocalServer = TRUE;
  529. }
  530. RegCloseKey(hKey);
  531. }
  532. if (!fFoundLocalServer)
  533. {
  534. lErr = RegOpenKeyEx(
  535. m_rghkCLSID[n],
  536. TEXT("LocalServer"),
  537. 0,
  538. KEY_ALL_ACCESS,
  539. &hKey);
  540. if (lErr == ERROR_SUCCESS)
  541. {
  542. dwSize = sizeof(szBuffer);
  543. lErr = RegQueryValueEx(
  544. hKey,
  545. TEXT(""),
  546. NULL,
  547. NULL,
  548. (BYTE *)szBuffer,
  549. &dwSize);
  550. if (lErr == ERROR_SUCCESS)
  551. {
  552. m_Page1.m_szServerPath = szBuffer;
  553. m_Page2.m_fLocal = TRUE;
  554. m_Page2.m_fCanBeLocal = TRUE;
  555. fFoundLocalServer = TRUE;
  556. }
  557. RegCloseKey(hKey);
  558. }
  559. }
  560. if (!fFoundLocalServer)
  561. {
  562. lErr = RegOpenKeyEx(
  563. m_rghkCLSID[n],
  564. TEXT("_LocalServer32"),
  565. 0,
  566. KEY_ALL_ACCESS,
  567. &hKey);
  568. if (lErr == ERROR_SUCCESS)
  569. {
  570. dwSize = sizeof(szBuffer);
  571. lErr = RegQueryValueEx(
  572. hKey,
  573. TEXT(""),
  574. NULL,
  575. NULL,
  576. (BYTE *)szBuffer,
  577. &dwSize);
  578. if (lErr == ERROR_SUCCESS)
  579. {
  580. m_Page1.m_szServerPath = szBuffer;
  581. m_Page2.m_fCanBeLocal = TRUE;
  582. fFoundLocalServer = TRUE;
  583. }
  584. RegCloseKey(hKey);
  585. }
  586. }
  587. if (!fFoundLocalServer)
  588. {
  589. lErr = RegOpenKeyEx(
  590. m_rghkCLSID[n],
  591. TEXT("_LocalServer"),
  592. 0,
  593. KEY_ALL_ACCESS,
  594. &hKey);
  595. if (lErr == ERROR_SUCCESS)
  596. {
  597. dwSize = sizeof(szBuffer);
  598. lErr = RegQueryValueEx(
  599. hKey,
  600. TEXT(""),
  601. NULL,
  602. NULL,
  603. (BYTE *)szBuffer,
  604. &dwSize);
  605. if (lErr == ERROR_SUCCESS)
  606. {
  607. m_Page1.m_szServerPath = szBuffer;
  608. m_Page2.m_fCanBeLocal = TRUE;
  609. fFoundLocalServer = TRUE;
  610. }
  611. RegCloseKey(hKey);
  612. }
  613. }
  614. n++;
  615. }
  616. return TRUE;
  617. }
  618. BOOL CClsidPropertySheet::ChangeCLSIDInfo(BOOL fLocal)
  619. {
  620. TCHAR szBuffer[MAX_PATH];
  621. CString szOld;
  622. CString szNew;
  623. CString szOld16;
  624. CString szNew16;
  625. DWORD dwSize;
  626. HKEY hKey;
  627. long lErr;
  628. if (fLocal)
  629. {
  630. szOld = TEXT("_LocalServer32");
  631. szNew = TEXT("LocalServer32");
  632. szOld16 = TEXT("_LocalServer");
  633. szNew16 = TEXT("LocalServer");
  634. }
  635. else
  636. {
  637. szOld = TEXT("LocalServer32");
  638. szNew = TEXT("_LocalServer32");
  639. szOld16 = TEXT("LocalServer");
  640. szNew16 = TEXT("_LocalServer");
  641. }
  642. unsigned n = 0;
  643. while (n < m_cCLSIDs)
  644. {
  645. // First do 32 servers
  646. lErr = RegOpenKeyEx(
  647. m_rghkCLSID[n],
  648. szOld,
  649. 0,
  650. KEY_ALL_ACCESS,
  651. &hKey);
  652. if (lErr == ERROR_SUCCESS)
  653. {
  654. dwSize = sizeof(szBuffer);
  655. lErr = RegQueryValueEx(
  656. hKey,
  657. TEXT(""),
  658. NULL,
  659. NULL,
  660. (BYTE *)szBuffer,
  661. &dwSize);
  662. if (lErr == ERROR_SUCCESS)
  663. {
  664. HKEY hKeyNew;
  665. DWORD dwDisp;
  666. lErr = RegCreateKeyEx(
  667. m_rghkCLSID[n],
  668. szNew,
  669. 0,
  670. NULL,
  671. REG_OPTION_NON_VOLATILE,
  672. KEY_ALL_ACCESS,
  673. NULL,
  674. &hKeyNew,
  675. &dwDisp);
  676. if (lErr == ERROR_SUCCESS)
  677. {
  678. lErr = RegSetValueEx(
  679. hKeyNew,
  680. TEXT(""),
  681. NULL,
  682. REG_SZ,
  683. (BYTE *)szBuffer,
  684. dwSize);
  685. RegCloseKey(hKeyNew);
  686. }
  687. }
  688. RegCloseKey(hKey);
  689. lErr = RegDeleteKey(m_rghkCLSID[n], szOld);
  690. }
  691. // Then do 16 servers
  692. lErr = RegOpenKeyEx(
  693. m_rghkCLSID[n],
  694. szOld16,
  695. 0,
  696. KEY_ALL_ACCESS,
  697. &hKey);
  698. if (lErr == ERROR_SUCCESS)
  699. {
  700. dwSize = sizeof(szBuffer);
  701. lErr = RegQueryValueEx(
  702. hKey,
  703. TEXT(""),
  704. NULL,
  705. NULL,
  706. (BYTE *)szBuffer,
  707. &dwSize);
  708. if (lErr == ERROR_SUCCESS)
  709. {
  710. HKEY hKeyNew;
  711. DWORD dwDisp;
  712. lErr = RegCreateKeyEx(
  713. m_rghkCLSID[n],
  714. szNew16,
  715. 0,
  716. NULL,
  717. REG_OPTION_NON_VOLATILE,
  718. KEY_ALL_ACCESS,
  719. NULL,
  720. &hKeyNew,
  721. &dwDisp);
  722. if (lErr == ERROR_SUCCESS)
  723. {
  724. lErr = RegSetValueEx(
  725. hKeyNew,
  726. TEXT(""),
  727. NULL,
  728. REG_SZ,
  729. (BYTE *)szBuffer,
  730. dwSize);
  731. RegCloseKey(hKeyNew);
  732. }
  733. }
  734. RegCloseKey(hKey);
  735. lErr = RegDeleteKey(m_rghkCLSID[n], szOld16);
  736. }
  737. n++;
  738. }
  739. return TRUE;
  740. }