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.

910 lines
23 KiB

  1. #include "stdafx.h"
  2. #include "userenv.h"
  3. #include "userenvp.h"
  4. #include "shlobj.h"
  5. #include "utils.h"
  6. #include "mddefw.h"
  7. #include "mdkey.h"
  8. #include "wizpages.h"
  9. #include "ocmanage.h"
  10. #include "setupapi.h"
  11. #include "k2suite.h"
  12. extern OCMANAGER_ROUTINES gHelperRoutines;
  13. DWORD GetUnattendedMode(HANDLE hUnattended, LPCTSTR szSubcomponent)
  14. {
  15. BOOL b = FALSE;
  16. TCHAR szLine[1024];
  17. DWORD dwMode = SubcompUseOcManagerDefault;
  18. CString csMsg;
  19. csMsg = _T("GetUnattendedMode ");
  20. csMsg += szSubcomponent;
  21. csMsg += _T("\n");
  22. DebugOutput((LPCTSTR)csMsg);
  23. // Try to get the line of interest
  24. if (hUnattended && (hUnattended != INVALID_HANDLE_VALUE))
  25. {
  26. b = SetupGetLineText(NULL, hUnattended, _T("Components"),
  27. szSubcomponent, szLine, sizeof(szLine)/sizeof(szLine[0]), NULL);
  28. if (b)
  29. {
  30. csMsg = szSubcomponent;
  31. csMsg += _T(" = ");
  32. csMsg += szLine;
  33. csMsg += _T("\n");
  34. DebugOutput((LPCTSTR)csMsg);
  35. // Parse the line
  36. if (!lstrcmpi(szLine, _T("on")))
  37. {
  38. dwMode = SubcompOn;
  39. }
  40. else if (!lstrcmpi(szLine, _T("off")))
  41. {
  42. dwMode = SubcompOff;
  43. }
  44. else if (!lstrcmpi(szLine, _T("default")))
  45. {
  46. dwMode = SubcompUseOcManagerDefault;
  47. }
  48. }
  49. else
  50. DebugOutput(_T("SetupGetLineText failed."));
  51. }
  52. return(dwMode);
  53. }
  54. DWORD GetUnattendedModeFromSetupMode(
  55. HANDLE hUnattended,
  56. DWORD dwComponent,
  57. LPCTSTR szSubcomponent)
  58. {
  59. BOOL b = FALSE;
  60. TCHAR szProperty[64];
  61. TCHAR szLine[1024];
  62. DWORD dwMode = SubcompUseOcManagerDefault;
  63. DWORD dwSetupMode;
  64. DebugOutput(_T("GetUnattendedModeFromSetupMode %s"), szSubcomponent);
  65. // Try to get the line of interest
  66. if (hUnattended && (hUnattended != INVALID_HANDLE_VALUE))
  67. {
  68. dwSetupMode = GetIMSSetupMode();
  69. switch (dwSetupMode)
  70. {
  71. case IIS_SETUPMODE_MINIMUM:
  72. case IIS_SETUPMODE_TYPICAL:
  73. case IIS_SETUPMODE_CUSTOM:
  74. // One of the fresh modes
  75. lstrcpy(szProperty, _T("FreshMode"));
  76. break;
  77. case IIS_SETUPMODE_UPGRADEONLY:
  78. case IIS_SETUPMODE_ADDEXTRACOMPS:
  79. // One of the upgrade modes
  80. lstrcpy(szProperty, _T("UpgradeMode"));
  81. break;
  82. case IIS_SETUPMODE_ADDREMOVE:
  83. case IIS_SETUPMODE_REINSTALL:
  84. case IIS_SETUPMODE_REMOVEALL:
  85. // One of the maintenance modes
  86. lstrcpy(szProperty, _T("MaintenanceMode"));
  87. break;
  88. default:
  89. // Error! Use defaults
  90. return(SubcompUseOcManagerDefault);
  91. }
  92. // Get the specified line
  93. b = SetupGetLineText(
  94. NULL,
  95. hUnattended,
  96. _T("Global"),
  97. szProperty,
  98. szLine,
  99. sizeof(szLine)/sizeof(szLine[0]),
  100. NULL);
  101. if (b)
  102. {
  103. DWORD dwOriginalMode;
  104. DebugOutput(_T("%s = %s"), szProperty, szLine);
  105. // See which setup mode we will end up with
  106. if (!lstrcmpi(szLine, _T("Minimal")))
  107. dwSetupMode = IIS_SETUPMODE_MINIMUM;
  108. else if (!lstrcmpi(szLine, _T("Typical")))
  109. dwSetupMode = IIS_SETUPMODE_TYPICAL;
  110. else if (!lstrcmpi(szLine, _T("Custom")))
  111. dwSetupMode = IIS_SETUPMODE_CUSTOM;
  112. else if (!lstrcmpi(szLine, _T("AddRemove")))
  113. dwSetupMode = IIS_SETUPMODE_ADDREMOVE;
  114. else if (!lstrcmpi(szLine, _T("RemoveAll")))
  115. dwSetupMode = IIS_SETUPMODE_REMOVEALL;
  116. else if (!lstrcmpi(szLine, _T("UpgradeOnly")))
  117. dwSetupMode = IIS_SETUPMODE_UPGRADEONLY;
  118. else if (!lstrcmpi(szLine, _T("AddExtraComps")))
  119. dwSetupMode = IIS_SETUPMODE_ADDEXTRACOMPS;
  120. else
  121. return(SubcompUseOcManagerDefault);
  122. // Get the custom unattended setting
  123. dwMode = GetUnattendedMode(hUnattended, szSubcomponent);
  124. // Do the right thing based on the setup mode
  125. SetIMSSetupMode(dwSetupMode);
  126. switch (dwSetupMode)
  127. {
  128. case IIS_SETUPMODE_MINIMUM:
  129. case IIS_SETUPMODE_TYPICAL:
  130. // Minimum & typical means the same:
  131. // Install all for SMTP, none for NNTP
  132. DebugOutput(_T("Unattended mode is MINIMUM/TYPICAL"));
  133. if (dwComponent == MC_IMS)
  134. dwMode = SubcompOn;
  135. else
  136. dwMode = SubcompOff;
  137. break;
  138. case IIS_SETUPMODE_CUSTOM:
  139. // For custom we use the custom setting
  140. DebugOutput(_T("Unattended mode is CUSTOM"));
  141. break;
  142. case IIS_SETUPMODE_UPGRADEONLY:
  143. // Return the original state
  144. DebugOutput(_T("Unattended mode is UPGRADEONLY"));
  145. dwMode = gHelperRoutines.QuerySelectionState(
  146. gHelperRoutines.OcManagerContext,
  147. szSubcomponent,
  148. OCSELSTATETYPE_ORIGINAL) ? SubcompOn : SubcompOff;
  149. break;
  150. case IIS_SETUPMODE_ADDEXTRACOMPS:
  151. // Turn it on only if the old state is off and the
  152. // custom state is on
  153. DebugOutput(_T("Unattended mode is ADDEXTRACOMPS"));
  154. dwOriginalMode = gHelperRoutines.QuerySelectionState(
  155. gHelperRoutines.OcManagerContext,
  156. szSubcomponent,
  157. OCSELSTATETYPE_ORIGINAL) ? SubcompOn : SubcompOff;
  158. if (dwOriginalMode == SubcompOff &&
  159. dwMode == SubcompOn)
  160. dwMode = SubcompOn;
  161. else
  162. dwMode = dwOriginalMode;
  163. break;
  164. case IIS_SETUPMODE_ADDREMOVE:
  165. // Return the custom setting
  166. DebugOutput(_T("Unattended mode is ADDREMOVE"));
  167. break;
  168. case IIS_SETUPMODE_REMOVEALL:
  169. // Kill everything
  170. DebugOutput(_T("Unattended mode is REMOVEALL"));
  171. dwMode = SubcompOff;
  172. break;
  173. }
  174. DebugOutput(_T("Unattended state for %s is %s"),
  175. szSubcomponent,
  176. (dwMode == SubcompOn)?_T("ON"):_T("OFF"));
  177. }
  178. else
  179. {
  180. if (GetLastError() != ERROR_LINE_NOT_FOUND)
  181. DebugOutput(_T("SetupGetLineText failed (%x)."), GetLastError());
  182. }
  183. }
  184. return(dwMode);
  185. }
  186. BOOL DetectExistingSmtpServers()
  187. {
  188. // Detect other mail servers
  189. CRegKey regMachine = HKEY_LOCAL_MACHINE;
  190. // System\CurrentControlSet\Services\MsExchangeIMC\Parameters
  191. CRegKey regSMTPParam( regMachine, REG_EXCHANGEIMCPARAMETERS, KEY_READ );
  192. if ((HKEY) regSMTPParam )
  193. {
  194. CString csCaption;
  195. DebugOutput(_T("IMC detected, suppressing SMTP"));
  196. if (!theApp.m_fIsUnattended && !theApp.m_fNTGuiMode)
  197. {
  198. MyLoadString(IDS_MESSAGEBOX_TEXT, csCaption);
  199. PopupOkMessageBox(IDS_SUPPRESS_SMTP, csCaption);
  200. }
  201. return(TRUE);
  202. }
  203. DebugOutput(_T("No other SMTP servers detected, installing IMS."));
  204. return(FALSE);
  205. }
  206. BOOL DetectExistingIISADMIN()
  207. {
  208. //
  209. // Detect is IISADMIN service exists
  210. //
  211. // This is to make sure we don't do any metabase operation if
  212. // IISADMIN doesn't exists, especially in the uninstall cases.
  213. //
  214. DWORD dwStatus = 0;
  215. dwStatus = InetQueryServiceStatus(SZ_MD_SERVICENAME);
  216. if (0 == dwStatus)
  217. {
  218. // some kind of error occur during InetQueryServiceStatus.
  219. DebugOutput(_T("DetectExistingIISADMIN() return FALSE"));
  220. return (FALSE);
  221. }
  222. return(TRUE);
  223. }
  224. BOOL InsertSetupString( LPCSTR REG_PARAMETERS )
  225. {
  226. // set up registry values
  227. CRegKey regMachine = HKEY_LOCAL_MACHINE;
  228. // System\CurrentControlSet\Services\NNTPSVC\Parameters
  229. CRegKey regParam( (LPCTSTR) REG_PARAMETERS, regMachine );
  230. if ((HKEY) regParam) {
  231. regParam.SetValue( _T("MajorVersion"), (DWORD)STAXNT5MAJORVERSION );
  232. regParam.SetValue( _T("MinorVersion"), (DWORD)STAXNT5MINORVERSION );
  233. regParam.SetValue( _T("InstallPath"), theApp.m_csPathInetsrv );
  234. switch (theApp.m_eNTOSType) {
  235. case OT_NTW:
  236. regParam.SetValue( _T("SetupString"), REG_SETUP_STRING_NT5WKSB3 );
  237. break;
  238. default:
  239. _ASSERT(!"Unknown OS type");
  240. // Fall through
  241. case OT_NTS:
  242. case OT_PDC_OR_BDC:
  243. case OT_PDC:
  244. case OT_BDC:
  245. regParam.SetValue( _T("SetupString"), REG_SETUP_STRING_NT5SRVB3 );
  246. break;
  247. }
  248. }
  249. return TRUE;
  250. }
  251. // Scans a multi-sz and finds the first occurrence of the
  252. // specified string
  253. LPTSTR ScanMultiSzForSz(LPTSTR szMultiSz, LPTSTR szSz)
  254. {
  255. LPTSTR lpTemp = szMultiSz;
  256. do
  257. {
  258. if (!lstrcmpi(lpTemp, szSz))
  259. return(lpTemp);
  260. lpTemp += lstrlen(lpTemp);
  261. lpTemp++;
  262. } while (*lpTemp != _T('\0'));
  263. return(NULL);
  264. }
  265. // Removes the said string from a MultiSz
  266. // This places a lot of faith in the caller!
  267. void RemoveSzFromMultiSz(LPTSTR szSz)
  268. {
  269. LPTSTR lpScan = szSz;
  270. TCHAR tcLastChar;
  271. lpScan += lstrlen(szSz);
  272. lpScan++;
  273. tcLastChar = _T('x');
  274. while ((tcLastChar != _T('\0')) ||
  275. (*lpScan != _T('\0')))
  276. {
  277. tcLastChar = *lpScan;
  278. *szSz++ = *lpScan++;
  279. }
  280. *szSz++ = _T('\0');
  281. // Properly terminate it if it's the last one
  282. if (*lpScan == _T('\0'))
  283. *szSz = _T('\0');
  284. }
  285. // This walks the multi-sz and returns a pointer between
  286. // the last string of a multi-sz and the second terminating
  287. // NULL
  288. LPTSTR GetEndOfMultiSz(LPTSTR szMultiSz)
  289. {
  290. LPTSTR lpTemp = szMultiSz;
  291. do
  292. {
  293. lpTemp += lstrlen(lpTemp);
  294. lpTemp++;
  295. } while (*lpTemp != _T('\0'));
  296. return(lpTemp);
  297. }
  298. // This appends a string to the end of a multi-sz
  299. // The buffer must be long enough
  300. BOOL AppendSzToMultiSz(LPTSTR szMultiSz, LPTSTR szSz, DWORD dwMaxSize)
  301. {
  302. LPTSTR szTemp = szMultiSz;
  303. DWORD dwLength = lstrlen(szSz);
  304. // If the string is empty, do not append!
  305. if (*szMultiSz == _T('\0') &&
  306. *(szMultiSz + 1) == _T('\0'))
  307. szTemp = szMultiSz;
  308. else
  309. {
  310. szTemp = GetEndOfMultiSz(szMultiSz);
  311. dwLength += (DWORD)(szTemp - szMultiSz);
  312. }
  313. if (dwLength >= dwMaxSize)
  314. return(FALSE);
  315. lstrcpy(szTemp, szSz);
  316. szMultiSz += dwLength;
  317. *szMultiSz = _T('\0');
  318. *(szMultiSz + 1) = _T('\0');
  319. return(TRUE);
  320. }
  321. BOOL AddServiceToDispatchList(LPTSTR szServiceName)
  322. {
  323. TCHAR szMultiSz[4096];
  324. DWORD dwSize = 4096;
  325. CRegKey RegInetInfo(REG_INETINFOPARAMETERS, HKEY_LOCAL_MACHINE);
  326. if ((HKEY)RegInetInfo)
  327. {
  328. // Default to empty string if not exists
  329. szMultiSz[0] = _T('\0');
  330. szMultiSz[1] = _T('\0');
  331. if (RegInetInfo.QueryValue(SZ_INETINFODISPATCH, szMultiSz, dwSize) == NO_ERROR)
  332. {
  333. // Walk the list to see if the value is already there
  334. if (ScanMultiSzForSz(szMultiSz, szServiceName))
  335. return(TRUE);
  336. }
  337. // Create the value and add it to the list
  338. if (!AppendSzToMultiSz(szMultiSz, szServiceName, dwSize))
  339. return(FALSE);
  340. // Get the size of the new Multi-sz
  341. dwSize = (DWORD)(GetEndOfMultiSz(szMultiSz) - szMultiSz) + 1;
  342. // Write the value back to the registry
  343. if (RegInetInfo.SetValue(SZ_INETINFODISPATCH, szMultiSz, dwSize * (DWORD) sizeof(TCHAR)) == NO_ERROR)
  344. return(TRUE);
  345. }
  346. // If the InetInfo key is not here, there isn't much we can do ...
  347. return(FALSE);
  348. }
  349. BOOL RemoveServiceFromDispatchList(LPTSTR szServiceName)
  350. {
  351. TCHAR szMultiSz[4096];
  352. DWORD dwSize = 4096;
  353. LPTSTR szTemp;
  354. BOOL fFound = FALSE;
  355. CRegKey RegInetInfo(HKEY_LOCAL_MACHINE, REG_INETINFOPARAMETERS);
  356. if ((HKEY)RegInetInfo)
  357. {
  358. if (RegInetInfo.QueryValue(SZ_INETINFODISPATCH, szMultiSz, dwSize) == NO_ERROR)
  359. {
  360. // Walk the list to see if the value is already there
  361. while (szTemp = ScanMultiSzForSz(szMultiSz, szServiceName))
  362. {
  363. RemoveSzFromMultiSz(szTemp);
  364. fFound = TRUE;
  365. }
  366. }
  367. // Write the value back to the registry if necessary, note we
  368. // will indicate success if the string is not found
  369. if (!fFound)
  370. return(TRUE);
  371. // Get the size of the new Multi-sz
  372. dwSize = (DWORD)(GetEndOfMultiSz(szMultiSz) - szMultiSz) + 1;
  373. // Write the value back to the registry
  374. if (RegInetInfo.SetValue(SZ_INETINFODISPATCH, szMultiSz, dwSize * (DWORD) sizeof(TCHAR)) == NO_ERROR)
  375. return(TRUE);
  376. }
  377. // If the InetInfo key is not here, there isn't much we can do ...
  378. return(FALSE);
  379. }
  380. void GetIISProgramGroup(CString &csGroupName, BOOL fIsMcisGroup)
  381. {
  382. TCHAR szName[_MAX_PATH];
  383. CString csTempName;
  384. UINT uType, uSize;
  385. if (fIsMcisGroup) {
  386. csGroupName = "";
  387. } else {
  388. // Get the NT program group name from the private data
  389. uSize = _MAX_PATH * sizeof(TCHAR);
  390. {
  391. // We use the default group name
  392. MyLoadString(IDS_DEFAULT_NT_PROGRAM_GROUP, csTempName);
  393. lstrcpy(szName, csTempName.GetBuffer(_MAX_PATH));
  394. csTempName.ReleaseBuffer();
  395. }
  396. csGroupName = szName;
  397. csGroupName += _T("\\");
  398. // Get the IIS program group name from the private data
  399. uSize = _MAX_PATH * sizeof(TCHAR);
  400. {
  401. // We use the default group name
  402. MyLoadString(IDS_DEFAULT_IIS_PROGRAM_GROUP, csTempName);
  403. lstrcpy(szName, csTempName.GetBuffer(_MAX_PATH));
  404. csTempName.ReleaseBuffer();
  405. }
  406. csGroupName += szName;
  407. }
  408. }
  409. void MyGetGroupPath(LPCTSTR szGroupName, LPTSTR szPath);
  410. BOOL GetFullPathToProgramGroup(DWORD dwMainComponent, CString &csGroupName, BOOL fIsMcisGroup)
  411. {
  412. // add items to the program group
  413. CString csTemp;
  414. TCHAR szPath[MAX_PATH];
  415. // Get the program group name from the private data
  416. GetIISProgramGroup(csTemp, fIsMcisGroup);
  417. // Get the system path to this menu item
  418. MyGetGroupPath((LPCTSTR)csTemp, szPath);
  419. csGroupName = szPath;
  420. // Load up the resource string for the group
  421. if (fIsMcisGroup)
  422. MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
  423. else
  424. MyLoadString(dwMainComponent == MC_IMS?IDS_PROGGROUP_MAIL:IDS_PROGGROUP_NEWS, csTemp);
  425. // Build the program group
  426. csGroupName += csTemp;
  427. DebugOutput(_T("Program group loaded: %s"), (LPCTSTR)csGroupName);
  428. return(TRUE);
  429. }
  430. BOOL GetFullPathToAdminGroup(DWORD dwMainComponent, CString &csGroupName)
  431. {
  432. // add items to the program group
  433. CString csTemp;
  434. TCHAR szPath[MAX_PATH];
  435. // Get the program group name from the private data
  436. MyLoadString( IDS_PROGGROUP_ADMINTOOLS, csTemp );
  437. // Get the system path to this menu item
  438. MyGetGroupPath((LPCTSTR)csTemp, szPath);
  439. csGroupName = szPath;
  440. DebugOutput(_T("Program group loaded: %s"), (LPCTSTR)csGroupName);
  441. return(TRUE);
  442. }
  443. BOOL RemoveProgramGroupIfEmpty(DWORD dwMainComponent, BOOL fIsMcisGroup)
  444. {
  445. // add items to the program group
  446. CString csGroupName;
  447. CString csTemp;
  448. TCHAR szPath[MAX_PATH];
  449. BOOL fResult;
  450. // Get the program group name from the private data
  451. GetIISProgramGroup(csTemp, fIsMcisGroup);
  452. // Get the system path to this menu item
  453. MyGetGroupPath((LPCTSTR)csTemp, szPath);
  454. csGroupName = szPath;
  455. // Load up the resource string for the group
  456. if (fIsMcisGroup)
  457. MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
  458. else
  459. MyLoadString(dwMainComponent == MC_IMS?IDS_PROGGROUP_MAIL:IDS_PROGGROUP_NEWS, csTemp);
  460. // Build the program group
  461. csGroupName += csTemp;
  462. DebugOutput(_T("Removing Program group: %s"), (LPCTSTR)csGroupName);
  463. fResult = RemoveDirectory((LPCTSTR)csGroupName);
  464. if (fResult && fIsMcisGroup)
  465. {
  466. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)csGroupName, 0);
  467. csGroupName = szPath;
  468. MyLoadString(IDS_MCIS_2_0, csTemp);
  469. csGroupName += csTemp;
  470. fResult = RemoveDirectory((LPCTSTR)csGroupName);
  471. }
  472. if (fResult)
  473. {
  474. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)csGroupName, 0);
  475. }
  476. return(fResult);
  477. }
  478. BOOL RemoveInternetShortcut(DWORD dwMainComponent, int dwDisplayNameId, BOOL fIsMcisGroup)
  479. {
  480. CString csItemPath;
  481. CString csDisplayName;
  482. MyLoadString(dwDisplayNameId, csDisplayName);
  483. // Build the full path to the program link
  484. GetFullPathToProgramGroup(dwMainComponent, csItemPath, fIsMcisGroup);
  485. csItemPath += _T("\\");
  486. csItemPath += csDisplayName;
  487. csItemPath += _T(".url");
  488. DebugOutput(_T("Removing shortcut file: %s"), (LPCTSTR)csItemPath);
  489. DeleteFile((LPCTSTR)csItemPath);
  490. SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, (LPCTSTR)csItemPath, 0);
  491. RemoveProgramGroupIfEmpty(dwMainComponent, fIsMcisGroup);
  492. return(TRUE);
  493. }
  494. BOOL RemoveNt5InternetShortcut(DWORD dwMainComponent, int dwDisplayNameId)
  495. {
  496. CString csItemPath;
  497. CString csDisplayName;
  498. MyLoadString(dwDisplayNameId, csDisplayName);
  499. // Build the full path to the program link
  500. GetFullPathToAdminGroup(dwMainComponent, csItemPath);
  501. csItemPath += _T("\\");
  502. csItemPath += csDisplayName;
  503. csItemPath += _T(".url");
  504. DebugOutput(_T("Removing shortcut file: %s"), (LPCTSTR)csItemPath);
  505. DeleteFile((LPCTSTR)csItemPath);
  506. SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, (LPCTSTR)csItemPath, 0);
  507. return(TRUE);
  508. }
  509. BOOL RemoveMCIS10MailProgramGroup()
  510. {
  511. CString csGroupName;
  512. CString csNiceName;
  513. MyLoadString(IDS_PROGGROUP_MCIS10_MAIL, csGroupName);
  514. MyLoadString(IDS_PROGITEM_MCIS10_MAIL_STARTPAGE, csNiceName);
  515. MyDeleteItem(csGroupName, csNiceName);
  516. MyLoadString(IDS_PROGITEM_MCIS10_MAIL_WEBADMIN, csNiceName);
  517. MyDeleteItemEx(csGroupName, csNiceName);
  518. return(TRUE);
  519. }
  520. BOOL RemoveMCIS10NewsProgramGroup()
  521. {
  522. CString csGroupName;
  523. CString csNiceName;
  524. // BINLIN:
  525. // BUGBUG: need to figure out how to get
  526. // the old MCIS 1.0 program group path
  527. MyLoadString(IDS_PROGGROUP_MCIS10_NEWS, csGroupName);
  528. MyLoadString(IDS_PROGITEM_MCIS10_NEWS_STARTPAGE, csNiceName);
  529. MyDeleteItem(csGroupName, csNiceName);
  530. MyLoadString(IDS_PROGITEM_MCIS10_NEWS_WEBADMIN, csNiceName);
  531. MyDeleteItemEx(csGroupName, csNiceName);
  532. return(TRUE);
  533. }
  534. BOOL RemoveUninstallEntries(LPCTSTR szInfFile)
  535. {
  536. // All components are removed, we will have to remove
  537. // the Add/Remove option from the control panel
  538. CRegKey regUninstall( HKEY_LOCAL_MACHINE, REG_UNINSTALL);
  539. if ((HKEY)regUninstall)
  540. regUninstall.DeleteTree(szInfFile);
  541. else
  542. return(FALSE);
  543. return(TRUE);
  544. }
  545. BOOL MyDeleteLink(LPTSTR lpszShortcut)
  546. {
  547. TCHAR szFile[_MAX_PATH];
  548. SHFILEOPSTRUCT fos;
  549. ZeroMemory(szFile, sizeof(szFile));
  550. lstrcpy(szFile, lpszShortcut);
  551. // only call SHFileOperation if this file/link exists
  552. if (0xFFFFFFFF != GetFileAttributes(szFile))
  553. {
  554. ZeroMemory(&fos, sizeof(fos));
  555. fos.hwnd = NULL;
  556. fos.wFunc = FO_DELETE;
  557. fos.pFrom = szFile;
  558. fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
  559. SHFileOperation(&fos);
  560. }
  561. return TRUE;
  562. }
  563. void MyGetGroupPath(LPCTSTR szGroupName, LPTSTR szPath)
  564. {
  565. int nLen = 0;
  566. LPITEMIDLIST pidlPrograms;
  567. szPath[0] = NULL;
  568. if (NOERROR != SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_PROGRAMS, &pidlPrograms)) return;
  569. if (!SHGetPathFromIDList(pidlPrograms, szPath)) return;
  570. nLen = lstrlen(szPath);
  571. if (szGroupName) {
  572. if (nLen == 0 || szPath[nLen-1] != _T('\\'))
  573. lstrcat(szPath, _T("\\"));
  574. lstrcat(szPath, szGroupName);
  575. }
  576. return;
  577. }
  578. BOOL MyAddGroup(LPCTSTR szGroupName)
  579. {
  580. TCHAR szPath[MAX_PATH];
  581. CString csPath;
  582. MyGetGroupPath(szGroupName, szPath);
  583. csPath = szPath;
  584. CreateLayerDirectory(csPath);
  585. SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, szPath, 0);
  586. return TRUE;
  587. }
  588. BOOL MyIsGroupEmpty(LPCTSTR szGroupName)
  589. {
  590. TCHAR szPath[MAX_PATH];
  591. TCHAR szFile[MAX_PATH];
  592. WIN32_FIND_DATA FindData;
  593. HANDLE hFind;
  594. BOOL bFindFile = TRUE;
  595. BOOL fReturn = TRUE;
  596. MyGetGroupPath(szGroupName, szPath);
  597. lstrcpy(szFile, szPath);
  598. lstrcat(szFile, _T("\\*.*"));
  599. hFind = FindFirstFile(szFile, &FindData);
  600. if (INVALID_HANDLE_VALUE != hFind)
  601. {
  602. while (bFindFile)
  603. {
  604. if(*(FindData.cFileName) != _T('.'))
  605. {
  606. fReturn = FALSE;
  607. break;
  608. }
  609. //find the next file
  610. bFindFile = FindNextFile(hFind, &FindData);
  611. }
  612. FindClose(hFind);
  613. }
  614. return fReturn;
  615. }
  616. BOOL MyDeleteGroup(LPCTSTR szGroupName)
  617. {
  618. TCHAR szPath[MAX_PATH];
  619. TCHAR szFile[MAX_PATH];
  620. SHFILEOPSTRUCT fos;
  621. WIN32_FIND_DATA FindData;
  622. HANDLE hFind;
  623. BOOL bFindFile = TRUE;
  624. BOOL fResult;
  625. MyGetGroupPath(szGroupName, szPath);
  626. //we can't remove a directory that is not empty, so we need to empty this one
  627. lstrcpy(szFile, szPath);
  628. lstrcat(szFile, _T("\\*.*"));
  629. ZeroMemory(&fos, sizeof(fos));
  630. fos.hwnd = NULL;
  631. fos.wFunc = FO_DELETE;
  632. fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
  633. hFind = FindFirstFile(szFile, &FindData);
  634. if (INVALID_HANDLE_VALUE != hFind)
  635. {
  636. while (bFindFile)
  637. {
  638. if(*(FindData.cFileName) != _T('.'))
  639. {
  640. //copy the path and file name to our temp buffer
  641. lstrcpy(szFile, szPath);
  642. lstrcat(szFile, _T("\\"));
  643. lstrcat(szFile, FindData.cFileName);
  644. //add a second NULL because SHFileOperation is looking for this
  645. lstrcat(szFile, _T("\0"));
  646. //delete the file
  647. fos.pFrom = szFile;
  648. SHFileOperation(&fos);
  649. }
  650. //find the next file
  651. bFindFile = FindNextFile(hFind, &FindData);
  652. }
  653. FindClose(hFind);
  654. }
  655. fResult = RemoveDirectory(szPath);
  656. if (fResult)
  657. {
  658. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, szPath, 0);
  659. }
  660. return(fResult);
  661. }
  662. void MyDeleteItem(LPCTSTR szGroupName, LPCTSTR szAppName)
  663. {
  664. TCHAR szPath[_MAX_PATH];
  665. MyGetGroupPath(szGroupName, szPath);
  666. lstrcat(szPath, _T("\\"));
  667. lstrcat(szPath, szAppName);
  668. lstrcat(szPath, _T(".lnk"));
  669. MyDeleteLink(szPath);
  670. if (MyIsGroupEmpty(szGroupName))
  671. MyDeleteGroup(szGroupName);
  672. }
  673. // Use to delete files with extension other than ".lnk"
  674. void MyDeleteItemEx(LPCTSTR szGroupName, LPCTSTR szAppName)
  675. {
  676. TCHAR szPath[_MAX_PATH];
  677. MyGetGroupPath(szGroupName, szPath);
  678. lstrcat(szPath, _T("\\"));
  679. lstrcat(szPath, szAppName);
  680. MyDeleteLink(szPath);
  681. if (MyIsGroupEmpty(szGroupName))
  682. MyDeleteGroup(szGroupName);
  683. }
  684. BOOL RemoveISMLink()
  685. {
  686. // add items to the program group
  687. CString csGroupName;
  688. CString csNiceName;
  689. CString csTemp;
  690. DebugOutput(_T("Removing ISM link ..."));
  691. // Get the program group name from the private data
  692. GetIISProgramGroup(csGroupName, TRUE);
  693. MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
  694. // Build the program group
  695. csGroupName += csTemp;
  696. MyLoadString(IDS_PROGITEM_ISM, csNiceName);
  697. MyDeleteItem(csGroupName, csNiceName);
  698. return(TRUE);
  699. }
  700. void GetInetpubPathFromMD(CString& csPathInetpub)
  701. {
  702. TCHAR szw3root[] = _T("\\wwwroot");
  703. TCHAR szPathInetpub[_MAX_PATH];
  704. ZeroMemory( szPathInetpub, sizeof(szPathInetpub) );
  705. CMDKey W3Key;
  706. DWORD dwScratch;
  707. DWORD dwType;
  708. DWORD dwLength;
  709. // Get W3Root path
  710. W3Key.OpenNode(_T("LM/W3Svc/1/Root"));
  711. if ( (METADATA_HANDLE)W3Key )
  712. {
  713. dwLength = _MAX_PATH;
  714. if (W3Key.GetData(3001, &dwScratch, &dwScratch,
  715. &dwType, &dwLength, (LPBYTE)szPathInetpub))
  716. {
  717. if (dwType == STRING_METADATA)
  718. {
  719. dwScratch = lstrlen(szw3root);
  720. dwLength = lstrlen(szPathInetpub);
  721. // If it ends with "\\wwwroot", then we copy the prefix into csPathInetpub
  722. if ((dwLength > dwScratch) &&
  723. !lstrcmpi(szPathInetpub + (dwLength - dwScratch), szw3root))
  724. {
  725. csPathInetpub.Empty();
  726. lstrcpyn( csPathInetpub.GetBuffer(512), szPathInetpub, (dwLength - dwScratch + 1));
  727. csPathInetpub.ReleaseBuffer();
  728. }
  729. // otherwise fall back to use the default...
  730. }
  731. }
  732. W3Key.Close();
  733. }
  734. return;
  735. }