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.

999 lines
21 KiB

  1. /*
  2. * NMPGMGRP - Tiny program to add and remove items from the program group.
  3. * Its initial purpose is to support Windows NT common program groups,
  4. * which are not supported by GRPCONV.
  5. *
  6. * Usage:
  7. *
  8. * NMPGMGRP /add [/common] [/g:"<group name>"] /n:"<program name>"
  9. * /p:"<program path>"
  10. * NMPGMGRP /delete [/common] [/g:"<group name>"] /n:"<program name>"
  11. *
  12. * NMPGMGRP /i /n:"<src mnmdd.dll>" /p:"<dst mnmdd.dll>" INSTALL NT DD
  13. * NMPGMGRP /u /n:"<src mnmdd.dll>" UNINSTALL NT DD
  14. *
  15. * NMPGMGRP /s [/q] /n:"<inf file>" /f"<friendly name>" SETUP
  16. *
  17. * /add is used to add a new program item.
  18. * /delete is used to remove an existing program item.
  19. *
  20. * /common indicates that this item belong in the common (as opposed to
  21. * per-user) program groups.
  22. *
  23. * <group name> is the name of the program group, expressed as a pathname
  24. * relative to the Programs group. For items in the Programs group,
  25. * this parameter should be omitted.
  26. *
  27. * <program name> is the name of the program, and is also used as the name
  28. * of the shortcut file itself.
  29. *
  30. * <program path> is the full path name of the program.
  31. *
  32. * <inf file> is the name of the installation inf.
  33. *
  34. * <friendly name> is the text to be used for any message box title.
  35. *
  36. * Limitations:
  37. *
  38. * Because some of these strings may contain spaces, the group name, program
  39. * name, and program path MUST be enclosed in quotes. Currently we do not
  40. * support strings with quotes in them.
  41. *
  42. * Some of the system functions used in this program are Unicode
  43. * specific, so this program will require some modifications to run on
  44. * Windows 95.
  45. *
  46. * Author:
  47. * DannyGl, 23 Mar 97
  48. */
  49. #include "precomp.h"
  50. #include "resource.h"
  51. #include <nmremote.h>
  52. #pragma intrinsic(memset)
  53. // DEBUG only -- Define debug zone
  54. #ifdef DEBUG
  55. HDBGZONE ghZone = NULL; // Node Controller Zones
  56. static PTCHAR rgZones[] = {
  57. TEXT("NMPgmGrp")
  58. };
  59. #endif // DEBUG
  60. // PROGRAM_ITEM_INFO structure:
  61. //
  62. // Intended to be passed as input to the CreateProgramItem and
  63. // DeleteProgramItem functions. Fields are:
  64. //
  65. // pszProgramGroup - The full path of the program group in which the
  66. // item is to be stored.
  67. // pszProgramName - The name of the program item.
  68. // pszProgramPath - The full path of the program.
  69. typedef
  70. struct tagProgramItemInfo
  71. {
  72. PTSTR pszProgramGroup;
  73. PTSTR pszProgramName;
  74. PTSTR pszProgramPath;
  75. } PROGRAM_ITEM_INFO, *PPROGRAM_ITEM_INFO;
  76. // Command line option data
  77. enum tagGroupOperation
  78. {
  79. GRPOP_NONE = 0,
  80. GRPOP_ADD,
  81. GRPOP_DEL,
  82. GRPOP_NTDDINSTALL,
  83. GRPOP_NTDDUNINSTALL,
  84. GRPOP_SETUP
  85. } g_goAction;
  86. BOOL g_fCommonGroup = FALSE;
  87. PTSTR g_pszGroupName = NULL;
  88. PTSTR g_pszProgramName = NULL;
  89. PTSTR g_pszProgramPath = NULL;
  90. PTSTR g_pszFriendlyName = NULL;
  91. BOOL g_fQuietInstall = FALSE;
  92. const TCHAR g_cszSetupDll[] = TEXT("advpack.dll");
  93. const TCHAR g_cszSetupEntry[] = TEXT("LaunchINFSection");
  94. typedef int (CALLBACK * PFNSETUPENTRY)(HWND hwnd, HINSTANCE hinst, LPTSTR lpszCmdLine, int nCmdShow);
  95. // ProcessCommandLineArgs:
  96. //
  97. // Get the command line and parse it into individual parameters using the
  98. // above global variables.
  99. //
  100. // Return: TRUE on success, FALSE if it could not parse the command line.
  101. BOOL
  102. ProcessCommandLineArgs(void)
  103. {
  104. PTSTR pszTemp;
  105. pszTemp = GetCommandLine();
  106. // Search for forward slashes
  107. pszTemp = (PTSTR) _StrChr(pszTemp, TEXT('/'));
  108. while (NULL != pszTemp)
  109. {
  110. PTSTR *ppszCurrentArg = NULL;
  111. switch(*++pszTemp)
  112. {
  113. case TEXT('S'):
  114. case TEXT('s'):
  115. ASSERT(GRPOP_NONE == g_goAction); // Check for duplicate parameter
  116. g_goAction = GRPOP_SETUP;
  117. break;
  118. case TEXT('I'):
  119. case TEXT('i'):
  120. //
  121. // Install NT-specific display driver stuff
  122. //
  123. ASSERT(GRPOP_NONE == g_goAction); // Check for duplicate parameter
  124. g_goAction = GRPOP_NTDDINSTALL;
  125. break;
  126. case TEXT('U'):
  127. case TEXT('u'):
  128. //
  129. // Uninstall NT-specific display driver stuff
  130. //
  131. ASSERT(GRPOP_NONE == g_goAction); // Check for duplicate parameter
  132. g_goAction = GRPOP_NTDDUNINSTALL;
  133. break;
  134. case TEXT('A'):
  135. case TEXT('a'):
  136. ASSERT(GRPOP_NONE == g_goAction); // Check for duplicate parameter
  137. g_goAction = GRPOP_ADD;
  138. break;
  139. case TEXT('D'):
  140. case TEXT('d'):
  141. ASSERT(GRPOP_NONE == g_goAction); // Check for duplicate parameter
  142. g_goAction = GRPOP_DEL;
  143. break;
  144. case TEXT('C'):
  145. case TEXT('c'):
  146. ASSERT(! g_fCommonGroup); // Check for duplicate parameter
  147. g_fCommonGroup = TRUE;
  148. break;
  149. case TEXT('Q'):
  150. case TEXT('q'):
  151. g_fQuietInstall = TRUE;
  152. break;
  153. case TEXT('G'):
  154. case TEXT('g'):
  155. if (NULL == ppszCurrentArg)
  156. {
  157. ppszCurrentArg = &g_pszGroupName;
  158. }
  159. // NO break HERE -- fall through
  160. case TEXT('N'):
  161. case TEXT('n'):
  162. if (NULL == ppszCurrentArg)
  163. {
  164. ppszCurrentArg = &g_pszProgramName;
  165. }
  166. // NO break HERE -- fall through
  167. case TEXT('P'):
  168. case TEXT('p'):
  169. if (NULL == ppszCurrentArg)
  170. {
  171. ppszCurrentArg = &g_pszProgramPath;
  172. }
  173. // NO break HERE -- fall through
  174. case TEXT('F'):
  175. case TEXT('f'):
  176. if (NULL == ppszCurrentArg)
  177. {
  178. ppszCurrentArg = &g_pszFriendlyName;
  179. }
  180. // ***** Processing for all string parameters *****
  181. ASSERT(NULL == *ppszCurrentArg); // Check for duplicate parameter
  182. // Save the string pointer after skipping past the colon and open quote
  183. ASSERT(TEXT(':') == pszTemp[1] && TEXT('\"') == pszTemp[2]);
  184. *ppszCurrentArg = pszTemp += 3;
  185. // Find the closing quote and set it to null, then skip past it
  186. // Note that we don't handle strings with quotes in them.
  187. pszTemp = (PTSTR) _StrChr(pszTemp, TEXT('\"'));
  188. ASSERT(NULL != pszTemp);
  189. if (NULL != pszTemp)
  190. {
  191. *pszTemp++ = TEXT('\0');
  192. }
  193. else
  194. {
  195. return FALSE;
  196. }
  197. break;
  198. default:
  199. ERROR_OUT(("Unknown parameter begins at %s", pszTemp));
  200. return FALSE;
  201. break;
  202. }
  203. // Find the next option flag
  204. ASSERT(NULL != pszTemp);
  205. pszTemp = (PTSTR) _StrChr(pszTemp, TEXT('/'));
  206. }
  207. // Return based on minimal parameter validation:
  208. // 1) The program name must be specified.
  209. // 2) Either add or delete must be specified.
  210. // 3) If add is specified, the program path must be specified
  211. switch (g_goAction)
  212. {
  213. case GRPOP_ADD:
  214. case GRPOP_NTDDINSTALL:
  215. return((NULL != g_pszProgramName) && (NULL != g_pszProgramPath));
  216. case GRPOP_DEL:
  217. case GRPOP_NTDDUNINSTALL:
  218. return(NULL != g_pszProgramName);
  219. case GRPOP_SETUP:
  220. return((NULL != g_pszProgramName) && (NULL != g_pszFriendlyName));
  221. default:
  222. return(FALSE);
  223. }
  224. }
  225. // GetFolderPathname:
  226. //
  227. // Use the official shell interfaces to retrieve the full pathname of a
  228. // a programs folder.
  229. //
  230. // Input:
  231. // ptstrPath, ccPath - The pointer to a size of the buffer in
  232. // which to store the path.
  233. // nFolder - The folder to locate, expressed as a CSIDL constant.
  234. // See SHGetSpecialFolderLocation for details.
  235. // pctstrSubFolder - A specific subfolder, can be NULL if not specified.
  236. // If specified, this is appended (after a backslash) to the path.
  237. //
  238. // Returns:
  239. // An HRESULT to indicate success or failure of the Shell methods.
  240. // The path is returned in <ptstrPath>.
  241. HRESULT
  242. GetFolderPathname(
  243. PTSTR ptstrPath,
  244. UINT cchPath,
  245. int nFolder,
  246. LPCTSTR pctstrSubFolder)
  247. {
  248. HRESULT hr;
  249. LPMALLOC pMalloc = NULL;
  250. LPSHELLFOLDER pDesktopFolder = NULL;
  251. LPITEMIDLIST pidlSpecialFolder = NULL;
  252. // Get the allocator object
  253. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  254. // Get the desktop object
  255. if (SUCCEEDED(hr))
  256. {
  257. hr = SHGetDesktopFolder(&pDesktopFolder);
  258. }
  259. // Get the special folder item ID
  260. if (SUCCEEDED(hr))
  261. {
  262. hr = SHGetSpecialFolderLocation(
  263. GetDesktopWindow(),
  264. nFolder,
  265. &pidlSpecialFolder);
  266. }
  267. // Retrieve the folder name
  268. STRRET strFolder;
  269. if (SUCCEEDED(hr))
  270. {
  271. strFolder.uType = STRRET_WSTR;
  272. hr = pDesktopFolder->GetDisplayNameOf(
  273. pidlSpecialFolder,
  274. SHGDN_FORPARSING,
  275. &strFolder);
  276. }
  277. if (SUCCEEDED(hr))
  278. {
  279. CUSTRING custrPath;
  280. switch(strFolder.uType)
  281. {
  282. case STRRET_WSTR:
  283. custrPath.AssignString(strFolder.pOleStr);
  284. break;
  285. case STRRET_OFFSET:
  286. custrPath.AssignString(((LPSTR) pidlSpecialFolder) + strFolder.uOffset);
  287. break;
  288. case STRRET_CSTR:
  289. custrPath.AssignString(strFolder.cStr);
  290. break;
  291. }
  292. ASSERT(NULL != (PTSTR) custrPath);
  293. lstrcpyn(ptstrPath, custrPath, cchPath);
  294. if (STRRET_WSTR == strFolder.uType)
  295. {
  296. pMalloc->Free(strFolder.pOleStr);
  297. }
  298. }
  299. // Append subgroup name, if it's specified
  300. if (SUCCEEDED(hr) && NULL != pctstrSubFolder)
  301. {
  302. // BUGBUG - We don't create this folder if it doesn't already exist
  303. int cchLen = lstrlen(ptstrPath);
  304. ASSERT((UINT) cchLen < cchPath);
  305. // Insert a path separator
  306. ptstrPath[cchLen++] = TEXT('\\');
  307. // Copy the subgroup
  308. lstrcpyn(ptstrPath + cchLen, pctstrSubFolder, cchPath - cchLen);
  309. }
  310. // Release resources
  311. if (pDesktopFolder)
  312. {
  313. pDesktopFolder->Release();
  314. }
  315. if (pMalloc)
  316. {
  317. if (pidlSpecialFolder)
  318. {
  319. pMalloc->Free(pidlSpecialFolder);
  320. }
  321. pMalloc->Release();
  322. }
  323. return hr;
  324. }
  325. // BuildLinkFileName:
  326. //
  327. // Inline utility function to construct the full file name of a link given its
  328. // directory name and item name.
  329. inline void
  330. BuildLinkFileName(
  331. OUT LPWSTR wszOutputPath,
  332. IN LPCTSTR pcszDirectory,
  333. IN LPCTSTR pcszFile)
  334. {
  335. // The file name is of the form <directory>\<file>.LNK
  336. #ifdef UNICODE
  337. static const WCHAR wszFileFormat[] = L"%s\\%s.LNK";
  338. #else // UNICODE
  339. static const WCHAR wszFileFormat[] = L"%hs\\%hs.LNK";
  340. #endif // UNICODE
  341. int cchSize;
  342. cchSize = wsprintfW(
  343. wszOutputPath,
  344. wszFileFormat,
  345. pcszDirectory,
  346. pcszFile);
  347. ASSERT(cchSize > ARRAY_ELEMENTS(wszFileFormat) - 1 && cchSize < MAX_PATH);
  348. }
  349. // CreateProgramItem:
  350. //
  351. // Use the official shell interfaces to create a shortcut to a program.
  352. //
  353. // Input: A pointer to a PROGRAM_ITEM_INFO structure, defined above.
  354. //
  355. // Returns:
  356. // An HRESULT to indicate success or failure of the Shell methods.
  357. HRESULT
  358. CreateProgramItem(
  359. PPROGRAM_ITEM_INFO ppii)
  360. {
  361. HRESULT hr;
  362. IShellLink *psl = NULL;
  363. IPersistFile *ppf = NULL;
  364. // Get the shell link object
  365. hr = CoCreateInstance(
  366. CLSID_ShellLink,
  367. NULL,
  368. CLSCTX_INPROC,
  369. IID_IShellLink,
  370. (LPVOID *) &psl);
  371. // Fill in the fields of the program group item
  372. if (SUCCEEDED(hr))
  373. {
  374. hr = psl->SetDescription(ppii->pszProgramName);
  375. }
  376. if (SUCCEEDED(hr))
  377. {
  378. hr = psl->SetPath(ppii->pszProgramPath);
  379. }
  380. // Save the link as a file
  381. if (SUCCEEDED(hr))
  382. {
  383. hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf);
  384. }
  385. if (SUCCEEDED(hr))
  386. {
  387. WCHAR wszFileName[MAX_PATH];
  388. BuildLinkFileName(
  389. wszFileName,
  390. ppii->pszProgramGroup,
  391. ppii->pszProgramName);
  392. hr = ppf->Save(wszFileName, TRUE);
  393. }
  394. // Release the objects we used
  395. if (ppf)
  396. {
  397. ppf->Release();
  398. }
  399. if (psl)
  400. {
  401. psl->Release();
  402. }
  403. return hr;
  404. }
  405. // DeleteProgramItem:
  406. //
  407. // Delete a shortcut to a program.
  408. //
  409. // Input: A pointer to a PROGRAM_ITEM_INFO structure, defined above.
  410. //
  411. // Returns:
  412. // An HRESULT to indicate success or failure of the Shell methods.
  413. HRESULT
  414. DeleteProgramItem(
  415. PPROGRAM_ITEM_INFO ppii)
  416. {
  417. HRESULT hr = S_OK;
  418. WCHAR wszFileName[MAX_PATH];
  419. BuildLinkFileName(
  420. wszFileName,
  421. ppii->pszProgramGroup,
  422. ppii->pszProgramName);
  423. if (! DeleteFileW(wszFileName))
  424. {
  425. WARNING_OUT(("DeleteFile failed"));
  426. hr = E_FAIL;
  427. }
  428. return hr;
  429. }
  430. //
  431. // NtDDInstall()
  432. // This does NT-specific display driver install stuff, which depends on
  433. // whether it's NT4 or NT5
  434. //
  435. //
  436. HRESULT NtDDInstall(LPTSTR pszOrigDd, LPTSTR pszNewDd)
  437. {
  438. HRESULT hr = E_FAIL;
  439. OSVERSIONINFO osvi;
  440. RegEntry re(NM_NT_DISPLAY_DRIVER_KEY, HKEY_LOCAL_MACHINE, FALSE);
  441. //
  442. // If NT4, set service key to disabled
  443. // If NT5, copy mnmdd.dll from NM dir to cur (system32) dir
  444. //
  445. osvi.dwOSVersionInfoSize = sizeof(osvi);
  446. if (!GetVersionEx(&osvi))
  447. {
  448. ERROR_OUT(("GetVersionEx() failed"));
  449. goto AllDone;
  450. }
  451. if ((osvi.dwPlatformId == VER_PLATFORM_WIN32s) ||
  452. (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
  453. {
  454. WARNING_OUT(("NT setup running on non-NT platform!"));
  455. goto AllDone;
  456. }
  457. if (osvi.dwMajorVersion >= 5)
  458. {
  459. //
  460. // This is NT5. Always set the service key to enabled (in case
  461. // the end user managed to munge it) and copy mnmdd.dll to the
  462. // current (system) directory. For example, if somebody had a
  463. // stand-alone version of a beta, uninstalled it, then installed
  464. // NM 3.0 proper--or same for 2.11.
  465. //
  466. re.SetValue(REGVAL_NM_NT_DISPLAY_DRIVER_ENABLED, NT_DRIVER_START_SYSTEM);
  467. if (!CopyFile(pszOrigDd, pszNewDd, FALSE))
  468. {
  469. WARNING_OUT(("CopyFile from %s to %s failed", pszOrigDd, pszNewDd));
  470. goto AllDone;
  471. }
  472. }
  473. else
  474. {
  475. // This is NT4. Set the disabled service key
  476. re.SetValue(REGVAL_NM_NT_DISPLAY_DRIVER_ENABLED, NT_DRIVER_START_DISABLED);
  477. }
  478. hr = S_OK;
  479. AllDone:
  480. return(hr);
  481. }
  482. //
  483. // NtDDUninstall()
  484. // This does NT-specific display driver uninstall stuff, which depends
  485. // on whether it's NT4 or NT5
  486. //
  487. HRESULT NtDDUninstall(LPTSTR pszOrigFile)
  488. {
  489. HRESULT hr = E_FAIL;
  490. OSVERSIONINFO osvi;
  491. //
  492. // If NT4, set service key to disabled
  493. // If NT5, delete mnmdd.dll from cur (system32) dir
  494. //
  495. osvi.dwOSVersionInfoSize = sizeof(osvi);
  496. if (!GetVersionEx(&osvi))
  497. {
  498. ERROR_OUT(("GetVersionEx() failed"));
  499. goto AllDone;
  500. }
  501. if ((osvi.dwPlatformId == VER_PLATFORM_WIN32s) ||
  502. (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
  503. {
  504. ERROR_OUT(("NT setup running on non-NT platform!"));
  505. goto AllDone;
  506. }
  507. if (osvi.dwMajorVersion >= 5)
  508. {
  509. // This is NT5. Delete mnmdd.dll from the current (system) directory
  510. if (!DeleteFile(pszOrigFile))
  511. {
  512. WARNING_OUT(("DeleteFile of %s failed", pszOrigFile));
  513. goto AllDone;
  514. }
  515. }
  516. else
  517. {
  518. // This is NT4. Set the disabled service key
  519. RegEntry re(NM_NT_DISPLAY_DRIVER_KEY, HKEY_LOCAL_MACHINE, FALSE);
  520. re.SetValue(REGVAL_NM_NT_DISPLAY_DRIVER_ENABLED,
  521. NT_DRIVER_START_DISABLED);
  522. }
  523. hr = S_OK;
  524. AllDone:
  525. return(hr);
  526. }
  527. UINT _MessageBox(HINSTANCE hInst, UINT uID, LPCTSTR lpCaption, UINT uType)
  528. {
  529. TCHAR szText[512];
  530. if (0 != LoadString(hInst, uID, szText, CCHMAX(szText)))
  531. {
  532. return MessageBox(NULL, szText, lpCaption, uType);
  533. }
  534. return IDCANCEL;
  535. }
  536. #define CONF_INIT_EVENT TEXT("CONF:Init")
  537. BOOL FIsNetMeetingRunning()
  538. {
  539. HANDLE hEvent;
  540. hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, SERVICE_STOP_EVENT);
  541. if (hEvent)
  542. {
  543. CloseHandle(hEvent);
  544. return TRUE;
  545. }
  546. hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, CONF_INIT_EVENT);
  547. if (hEvent)
  548. {
  549. CloseHandle(hEvent);
  550. return TRUE;
  551. }
  552. return FALSE;
  553. }
  554. BOOL FIsNT5()
  555. {
  556. OSVERSIONINFO osvi;
  557. osvi.dwOSVersionInfoSize = sizeof(osvi);
  558. if (GetVersionEx(&osvi))
  559. {
  560. if ((osvi.dwPlatformId != VER_PLATFORM_WIN32s) &&
  561. (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS))
  562. {
  563. if (osvi.dwMajorVersion >= 5)
  564. {
  565. return TRUE;
  566. }
  567. }
  568. }
  569. else
  570. {
  571. ERROR_OUT(("GetVersionEx() failed"));
  572. }
  573. return FALSE;
  574. }
  575. #define IE4_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Last Update\\IEXPLOREV4")
  576. BOOL FIsIE4Installed()
  577. {
  578. RegEntry re(IE4_KEY, HKEY_LOCAL_MACHINE, FALSE);
  579. if (ERROR_SUCCESS != re.GetError())
  580. {
  581. return FALSE;
  582. }
  583. return TRUE;
  584. }
  585. #define INTEL_KEY1 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vphone.exe")
  586. #define INTEL_KEY2 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\rvp.exe")
  587. #define INTEL_KEY3 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vp30.exe")
  588. #define INTEL_NM_VERSION_SZ TEXT("NetMeeting")
  589. #define INTEL_NM_VERSION_DW 3
  590. #define PANTHER_KEY TEXT("CLSID\\{690968D0-418C-11D1-8E0B-00A0C95A83DA}\\Version")
  591. #define PANTHER_VERSION_VALUE TEXT("1.0")
  592. #define TRANSPORTS_KEY TEXT("SOFTWARE\\Microsoft\\Conferencing\\Transports")
  593. #define REGKEY_PSTN TEXT("PSTN")
  594. #define REGKEY_TCPIP TEXT("TCPIP")
  595. #define REGKEY_IPX TEXT("IPX")
  596. #define REGKEY_NETBIOS TEXT("NETBIOS")
  597. #define REGKEY_DIRCB TEXT("DIRCB")
  598. long GetIntelVersion(LPCTSTR pszKey)
  599. {
  600. RegEntry re(pszKey, HKEY_LOCAL_MACHINE, FALSE);
  601. if (ERROR_SUCCESS != re.GetError())
  602. {
  603. return -1;
  604. }
  605. return re.GetNumber(INTEL_NM_VERSION_SZ, 0);
  606. }
  607. BOOL FAnyBadIntelApps()
  608. {
  609. long lVersion;
  610. lVersion = GetIntelVersion(INTEL_KEY1);
  611. if (0 > lVersion)
  612. {
  613. lVersion = GetIntelVersion(INTEL_KEY2);
  614. if (0 > lVersion)
  615. {
  616. lVersion = GetIntelVersion(INTEL_KEY3);
  617. }
  618. }
  619. return ((0 <= lVersion) && (3 > lVersion));
  620. }
  621. BOOL FAnyBadPantherApps()
  622. {
  623. RegEntry re(PANTHER_KEY, HKEY_CLASSES_ROOT, FALSE);
  624. if (ERROR_SUCCESS != re.GetError())
  625. {
  626. return FALSE;
  627. }
  628. LPCTSTR pszVersion = re.GetString(TEXT(""));
  629. return 0 == lstrcmp(pszVersion, PANTHER_VERSION_VALUE);
  630. }
  631. BOOL FAnyUnknownTransports()
  632. {
  633. RegEntry TransportsKey(TRANSPORTS_KEY, HKEY_LOCAL_MACHINE, FALSE);
  634. RegEnumSubKeys EnumTransports(&TransportsKey);
  635. while( 0 == EnumTransports.Next() )
  636. {
  637. LPCTSTR pszName = EnumTransports.GetName();
  638. if ((0 != lstrcmpi(pszName, REGKEY_PSTN)) &&
  639. (0 != lstrcmpi(pszName, REGKEY_TCPIP)) &&
  640. (0 != lstrcmpi(pszName, REGKEY_IPX)) &&
  641. (0 != lstrcmpi(pszName, REGKEY_NETBIOS)) &&
  642. (0 != lstrcmpi(pszName, REGKEY_DIRCB)))
  643. {
  644. return TRUE;
  645. }
  646. }
  647. return FALSE;
  648. }
  649. BOOL FAnyIncompatibleApps()
  650. {
  651. return FAnyUnknownTransports() || FAnyBadIntelApps() || FAnyBadPantherApps();
  652. }
  653. HRESULT Setup(HINSTANCE hInst, LPTSTR pszInfFile, LPTSTR pszFriendlyName, BOOL fQuietInstall)
  654. {
  655. if (FIsNT5())
  656. {
  657. _MessageBox(hInst, IDS_SETUP_WIN2K, pszFriendlyName, MB_OK);
  658. // if the SHFT-CTRL was pressed continue with the install, else exit
  659. if ((0 == GetAsyncKeyState(VK_CONTROL)) ||
  660. (0 == GetAsyncKeyState(VK_SHIFT)))
  661. {
  662. return S_FALSE;
  663. }
  664. }
  665. if (!FIsIE4Installed())
  666. {
  667. _MessageBox(hInst, IDS_SETUP_IE4, pszFriendlyName, MB_OK);
  668. return S_FALSE;
  669. }
  670. while (FIsNetMeetingRunning())
  671. {
  672. if (IDCANCEL == _MessageBox(hInst, IDS_SETUP_RUNNING, pszFriendlyName, MB_OKCANCEL))
  673. {
  674. return S_FALSE;
  675. }
  676. }
  677. if (!fQuietInstall)
  678. {
  679. if (FAnyIncompatibleApps())
  680. {
  681. if (IDNO == _MessageBox(hInst, IDS_SETUP_INCOMPATIBLE, pszFriendlyName, MB_YESNO))
  682. {
  683. return S_FALSE;
  684. }
  685. }
  686. }
  687. HRESULT hr = S_FALSE;
  688. HINSTANCE hLib = LoadLibrary(g_cszSetupDll);
  689. if (NULL != hLib)
  690. {
  691. PFNSETUPENTRY pfnEntry = (PFNSETUPENTRY)GetProcAddress(hLib, g_cszSetupEntry);
  692. if (pfnEntry)
  693. {
  694. TCHAR szArgs[MAX_PATH];
  695. lstrcpy(szArgs, pszInfFile);
  696. if (fQuietInstall)
  697. {
  698. lstrcat(szArgs, TEXT(",,1,N"));
  699. }
  700. else
  701. {
  702. lstrcat(szArgs, TEXT(",,,N"));
  703. }
  704. int iRet = pfnEntry(NULL, GetModuleHandle(NULL), szArgs, SW_SHOWNORMAL);
  705. if (0 == iRet)
  706. {
  707. if (!fQuietInstall)
  708. {
  709. _MessageBox(hInst, IDS_SETUP_SUCCESS, pszFriendlyName, MB_OK);
  710. }
  711. hr = S_OK;
  712. }
  713. }
  714. else
  715. {
  716. ERROR_OUT(("Could not find setup DLL entry point"));
  717. }
  718. FreeLibrary(hLib);
  719. }
  720. else
  721. {
  722. ERROR_OUT(("Could not load setup DLL"));
  723. }
  724. return hr;
  725. }
  726. // main:
  727. //
  728. // The entry point of the program, it pulls everything together using the
  729. // above utility functions.
  730. void __cdecl
  731. main(
  732. void)
  733. {
  734. HRESULT hr;
  735. HINSTANCE hInstance;
  736. BOOL fErrorReported = FALSE;
  737. TCHAR szFolderPath[MAX_PATH];
  738. // Initialization
  739. hInstance = GetModuleHandle(NULL);
  740. DBGINIT(&ghZone, rgZones);
  741. DBG_INIT_MEMORY_TRACKING(hInstance);
  742. hr = CoInitialize(NULL);
  743. // Process the command line.
  744. if (SUCCEEDED(hr))
  745. {
  746. hr = ProcessCommandLineArgs() ? S_OK : E_INVALIDARG;
  747. }
  748. else if (!fErrorReported)
  749. {
  750. ERROR_OUT(("CoInitialize fails"));
  751. fErrorReported = TRUE;
  752. }
  753. // Retreive the path of the Programs folder
  754. if (SUCCEEDED(hr))
  755. {
  756. if ((g_goAction != GRPOP_NTDDINSTALL) &&
  757. (g_goAction != GRPOP_NTDDUNINSTALL) &&
  758. (g_goAction != GRPOP_SETUP))
  759. {
  760. hr = GetFolderPathname(
  761. szFolderPath,
  762. CCHMAX(szFolderPath),
  763. g_fCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS,
  764. g_pszGroupName);
  765. }
  766. }
  767. else if (!fErrorReported)
  768. {
  769. ERROR_OUT(("Invalid command line parameters specified."));
  770. fErrorReported = TRUE;
  771. }
  772. // Add or delete the program item, as appropriate
  773. if (SUCCEEDED(hr))
  774. {
  775. PROGRAM_ITEM_INFO pii;
  776. switch(g_goAction)
  777. {
  778. case GRPOP_NTDDINSTALL:
  779. //
  780. // Hack: Use program name for source mnmdd.dll
  781. // Use program path for dest mnmdd.dll
  782. //
  783. hr = NtDDInstall(g_pszProgramName, g_pszProgramPath);
  784. break;
  785. case GRPOP_NTDDUNINSTALL:
  786. //
  787. // Hack: Use program name for source mnmdd.dll
  788. //
  789. hr = NtDDUninstall(g_pszProgramName);
  790. break;
  791. case GRPOP_ADD:
  792. pii.pszProgramGroup = szFolderPath;
  793. pii.pszProgramName = g_pszProgramName;
  794. pii.pszProgramPath = g_pszProgramPath;
  795. hr = CreateProgramItem(&pii);
  796. break;
  797. case GRPOP_DEL:
  798. pii.pszProgramGroup = szFolderPath;
  799. pii.pszProgramName = g_pszProgramName;
  800. hr = DeleteProgramItem(&pii);
  801. break;
  802. case GRPOP_SETUP:
  803. hr = Setup(hInstance, g_pszProgramName, g_pszFriendlyName, g_fQuietInstall);
  804. break;
  805. default:
  806. ERROR_OUT(("No operation type specified"));
  807. hr = E_INVALIDARG;
  808. break;
  809. }
  810. }
  811. else if (!fErrorReported)
  812. {
  813. ERROR_OUT(("GetFolderPathname returns %lu", hr));
  814. fErrorReported = TRUE;
  815. }
  816. // Process cleanup
  817. CoUninitialize();
  818. DBG_CHECK_MEMORY_TRACKING(hInstance);
  819. DBGDEINIT(&ghZone);
  820. ExitProcess(SUCCEEDED(hr) ? 0 : 2);
  821. }