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.

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