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.

669 lines
20 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: pbasetup.cpp
  4. //
  5. // Module: PBASETUP.EXE
  6. //
  7. // Synopsis: PBA stand alone installer for ValueAdd
  8. //
  9. // Copyright (c) 1999 Microsoft Corporation
  10. //
  11. // Author: v-vijayb Created 05/25/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "pbamaster.h"
  15. #include "cmplat.h"
  16. // This is really ugly, we need to consolidate our platform detection code between CM and
  17. // the setup components.
  18. BOOL IsAtLeastNT5()
  19. {
  20. CPlatform plat;
  21. return plat.IsAtLeastNT5();
  22. }
  23. #define OS_NT5 (IsAtLeastNT5())
  24. #include "MemberOfGroup.cpp"
  25. TCHAR g_szAppTitle[MAX_PATH]; // global buffer for app. title
  26. const TCHAR* const c_pszPBAStpMutex = TEXT("Phone Book Administration Installer");
  27. HRESULT UnregisterAndDeleteDll(PCSTR pszFile);;
  28. HRESULT RegisterDll(PCSTR pszFile);
  29. BOOL UninstallPBA(HINSTANCE hInstance, LPCSTR szInfPath);
  30. BOOL IsAdmin(void);
  31. int WINAPI WinMain (HINSTANCE, // hInstance
  32. HINSTANCE, //hPrevInstance
  33. PSTR, // szCmdLine
  34. int) //iCmdShow
  35. {
  36. HINSTANCE hInstance = GetModuleHandleA(NULL);
  37. TCHAR szMsg[MAX_PATH+1];
  38. TCHAR szTemp[MAX_PATH+1];
  39. TCHAR szInfPath[MAX_PATH+1];
  40. TCHAR szCurrentDir[MAX_PATH+1];
  41. DWORD idMsgEnd;
  42. DWORD dwFlags;
  43. CPlatform pPlatForm;
  44. LPTSTR pszCommandLine;
  45. const DWORD c_dwNormal = 0;
  46. TCHAR c_pszUninstallMode[] = TEXT("/u");
  47. const DWORD c_dwUninstallMode = 0x1;
  48. BOOL bUsageError = FALSE;
  49. BOOL bAnotherInstanceRunning = FALSE;
  50. const int c_NumArgs = 1;
  51. MYVERIFY(0 != LoadString(hInstance, IDS_APP_TITLE, g_szAppTitle, MAX_PATH));
  52. if (!pPlatForm.IsAtLeastNT5())
  53. {
  54. MYVERIFY(0 != LoadString(hInstance, IDS_NOT_NT5, szMsg, MAX_PATH));
  55. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
  56. return (-1);
  57. }
  58. //
  59. // check that the user has sufficient permissions
  60. //
  61. if (!IsAdmin())
  62. {
  63. MYVERIFY(0 != LoadString(hInstance, IDS_NOPERMS_MSG, szMsg, MAX_PATH));
  64. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
  65. return (-1);
  66. }
  67. //
  68. // Get the Command Line
  69. //
  70. pszCommandLine = GetCommandLine();
  71. //
  72. // Setup the Class to process the command line args
  73. //
  74. ZeroMemory(szTemp, sizeof(szTemp));
  75. ZeroMemory(szInfPath, sizeof(szInfPath));
  76. ArgStruct Args[c_NumArgs];
  77. Args[0].pszArgString = c_pszUninstallMode;
  78. Args[0].dwFlagModifier = c_dwUninstallMode;
  79. { // Make sure ArgProcessor gets destructed properly and we don't leak mem
  80. CProcessCmdLn ArgProcessor(c_NumArgs, (ArgStruct*)Args, TRUE,
  81. TRUE); //bSkipFirstToken == TRUE, bBlankCmdLnOkay == TRUE
  82. if (ArgProcessor.GetCmdLineArgs(pszCommandLine, &dwFlags, szTemp, MAX_PATH))
  83. {
  84. CNamedMutex CmPBAMutex;
  85. if (CmPBAMutex.Lock(c_pszPBAStpMutex, FALSE, 0))
  86. {
  87. //
  88. // We got the mutex lock, so Construct the Inf Paths and continue.
  89. // Note that we don't use any file arguments passed into cmakstp.
  90. // It is setup to do so, but we don't need it.
  91. //
  92. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szCurrentDir));
  93. MYVERIFY(CELEMS(szInfPath) > (UINT)wsprintf(szInfPath, TEXT("%s\\pbasetup.inf"), szCurrentDir));
  94. if (c_dwNormal == dwFlags)
  95. {
  96. if (InstallPBA(hInstance, szInfPath))
  97. {
  98. MYVERIFY(0 != LoadString(hInstance, IDS_SUCCESSFUL, szMsg, MAX_PATH));
  99. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
  100. }
  101. }
  102. else if (c_dwUninstallMode & dwFlags)
  103. {
  104. // Confirm if the user wants to remove the program
  105. MYVERIFY(0 != LoadString(hInstance, IDS_REMOVEPBA, szMsg, MAX_PATH));
  106. if (MessageBox(NULL, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND) != IDYES)
  107. {
  108. ExitProcess(0);
  109. return (0);
  110. }
  111. if (UninstallPBA(hInstance, szTemp))
  112. {
  113. MYVERIFY(0 != LoadString(hInstance, IDS_REMOVESUCCESSFUL, szMsg, MAX_PATH));
  114. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
  115. }
  116. }
  117. else
  118. {
  119. //
  120. // unsupported switch
  121. //
  122. bUsageError = TRUE;
  123. }
  124. }
  125. else
  126. {
  127. bAnotherInstanceRunning = TRUE;
  128. }
  129. }
  130. else
  131. {
  132. bUsageError = TRUE;
  133. }
  134. }
  135. if (bUsageError)
  136. {
  137. MYVERIFY(0 != LoadString(hInstance, IDS_USAGE_MSG, szMsg, MAX_PATH));
  138. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
  139. }
  140. else if (bAnotherInstanceRunning)
  141. {
  142. MYVERIFY(0 != LoadString(hInstance, IDS_INUSE_MSG, szMsg, MAX_PATH));
  143. MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
  144. }
  145. ExitProcess(0);
  146. return (0);
  147. }
  148. const TCHAR* const c_szDaoClientsPath = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\DAO\\Clients");
  149. const TCHAR* c_szMSSharedDAO360Path = TEXT("Microsoft Shared\\DAO");
  150. const TCHAR* c_szCommonFilesDir = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
  151. //+---------------------------------------------------------------------------
  152. //
  153. // Function: HrGetPbaInstallPath
  154. //
  155. // Purpose: Get the install path for pbadmin.exe.
  156. //
  157. // Arguments: pszCpaPath -- buffer to hold the install path of PBA.
  158. // dwNumChars -- the number of characters that the buffer can hold.
  159. //
  160. //
  161. // Returns: S_OK if successfull, Win32 error otherwise.
  162. //
  163. // Author: quintinb 19 OCT 1998
  164. //
  165. // Notes:
  166. //
  167. HRESULT HrGetPbaInstallPath(PTCHAR pszCpaPath, DWORD dwNumChars)
  168. {
  169. HRESULT hr = E_FAIL;
  170. HKEY hKey;
  171. BOOL bFound = FALSE;
  172. DWORD lError;
  173. // We need to setup the custom DIRID so that CPA will install
  174. // to the correct location. First get the path from the system.
  175. //
  176. ZeroMemory(pszCpaPath, sizeof(TCHAR)*dwNumChars);
  177. lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, 0, KEY_READ, &hKey);
  178. if (lError == ERROR_SUCCESS)
  179. {
  180. TCHAR szCurrentValue[MAX_PATH+1];
  181. TCHAR szCurrentData[MAX_PATH+1];
  182. DWORD dwValueSize = MAX_PATH;
  183. DWORD dwDataSize = MAX_PATH;
  184. DWORD dwType;
  185. DWORD dwIndex = 0;
  186. hr = S_OK;
  187. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
  188. (LPBYTE)szCurrentData, &dwDataSize))
  189. {
  190. _strlwr(szCurrentValue);
  191. if (NULL != strstr(szCurrentValue, TEXT("pbadmin.exe")))
  192. {
  193. //
  194. // Then we have found the PBA path
  195. //
  196. TCHAR* pszTemp = strrchr(szCurrentValue, '\\');
  197. if (NULL != pszTemp)
  198. {
  199. *pszTemp = L'\0';
  200. lstrcpy(pszCpaPath, szCurrentValue);
  201. bFound = TRUE;
  202. break;
  203. }
  204. }
  205. dwValueSize = MAX_PATH;
  206. dwDataSize = MAX_PATH;
  207. dwIndex++;
  208. }
  209. RegCloseKey(hKey);
  210. }
  211. if (!bFound)
  212. {
  213. BOOL bTmp;
  214. // This is a fresh install of PBA, don't return an error
  215. //
  216. bTmp = SHGetSpecialFolderPath(NULL, pszCpaPath, CSIDL_PROGRAM_FILES, FALSE);
  217. if (bTmp)
  218. {
  219. lstrcat(pszCpaPath, TEXT("\\PBA"));
  220. hr = S_OK;
  221. }
  222. else
  223. {
  224. hr = HRESULT_FROM_WIN32(GetLastError());
  225. }
  226. }
  227. return hr;
  228. }
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Function: RefCountPbaSharedDlls
  232. //
  233. // Purpose: Reference count and register/unregister all of the PBAdmin
  234. // shared components.
  235. //
  236. // Arguments: BOOL bIncrement -- if TRUE, then increment the ref count,
  237. // else decrement it
  238. //
  239. //
  240. // Returns: S_OK if successfull, Win32 error otherwise.
  241. //
  242. // Author: quintinb 9 OCT 1998
  243. //
  244. // Notes:
  245. //
  246. HRESULT RefCountPbaSharedDlls(BOOL bIncrement)
  247. {
  248. HRESULT hr = S_OK;
  249. HKEY hKey;
  250. TCHAR szSystemDir[MAX_PATH+1];
  251. TCHAR szDaoPath[MAX_PATH+1], szCommonFilesPath[MAX_PATH+1];
  252. DWORD dwSize;
  253. DWORD dwCount;
  254. LONG lResult;
  255. const UINT uNumDlls = 5;
  256. const UINT uStringLen = 12 + 1;
  257. const TCHAR* const c_szSsFmt = TEXT("%s\\%s");
  258. const TCHAR* const c_szSharedDllsPath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDlls");
  259. TCHAR mszDlls[uNumDlls][uStringLen] = { "comctl32.ocx",
  260. "comdlg32.ocx",
  261. "msinet.ocx",
  262. "tabctl32.ocx",
  263. "dao360.dll"
  264. };
  265. TCHAR mszDllPaths[uNumDlls][MAX_PATH];
  266. //
  267. // All of the Dlls that we ref count are in the system directory, except for Dao350.dll.
  268. // Thus we want to append the system directory path to our filenames and handle dao last.
  269. //
  270. if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
  271. {
  272. return E_UNEXPECTED;
  273. }
  274. for (int i = 0; i < (uNumDlls-1) ; i++)
  275. {
  276. wsprintf(mszDllPaths[i], c_szSsFmt, szSystemDir, mszDlls[i]);
  277. }
  278. //
  279. // Now write out the dao360.dll path.
  280. //
  281. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szCommonFilesDir, 0, NULL,
  282. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize))
  283. {
  284. dwSize = sizeof(szCommonFilesPath);
  285. lResult = RegQueryValueEx(hKey, TEXT("CommonFilesDir"), NULL, NULL,(LPBYTE)szCommonFilesPath, &dwSize);
  286. RegCloseKey(hKey);
  287. }
  288. if (ERROR_SUCCESS != lResult)
  289. {
  290. _tcscpy(szCommonFilesPath, TEXT("c:\\Program Files\\Common Files"));
  291. }
  292. wsprintf(szDaoPath, TEXT("%s\\%s"), szCommonFilesPath, c_szMSSharedDAO360Path);
  293. wsprintf(mszDllPaths[i], c_szSsFmt, szDaoPath, mszDlls[i]);
  294. //
  295. // Open the shared DLL key and start enumerating our multi-sz with all of our dll's
  296. // to add.
  297. //
  298. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szSharedDllsPath,
  299. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize)) // using dwSize as a temp to hold the disposition value
  300. {
  301. for (int i=0; i < uNumDlls; i++)
  302. {
  303. dwSize = sizeof(DWORD);
  304. lResult = RegQueryValueEx(hKey, mszDllPaths[i], NULL, NULL,(LPBYTE)&dwCount, &dwSize);
  305. if (ERROR_SUCCESS == lResult)
  306. {
  307. //
  308. // Increment or decrement as appropriate. Make sure not to decrement 0
  309. //
  310. if (0 != dwCount || bIncrement)
  311. {
  312. dwCount = dwCount + (bIncrement ? 1 : -1);
  313. }
  314. }
  315. else if (ERROR_FILE_NOT_FOUND == lResult)
  316. {
  317. if (bIncrement)
  318. {
  319. //
  320. // The the value doesn't yet exist. Set the count to 1.
  321. //
  322. dwCount = 1;
  323. }
  324. else
  325. {
  326. //
  327. // We are decrementing and we couldn't find the DLL, nothing to
  328. // change for the count but we should still delete the dll.
  329. //
  330. dwCount = 0;
  331. }
  332. }
  333. else
  334. {
  335. hr = S_FALSE;
  336. continue;
  337. }
  338. //
  339. // Not that we have determined the ref count, do something about it.
  340. //
  341. if (dwCount == 0)
  342. {
  343. //
  344. // We don't want to delete dao350.dll, but otherwise we need to delete
  345. // the file if it has a zero refcount.
  346. //
  347. if (CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, mszDlls[i], -1, TEXT("dao360.dll"), -1))
  348. {
  349. hr = UnregisterAndDeleteDll(mszDllPaths[i]);
  350. if (FAILED(hr))
  351. {
  352. //
  353. // Don't fail the setup over a file that we couldn't unregister or
  354. // couldn't delete
  355. //
  356. hr = S_FALSE;
  357. }
  358. }
  359. RegDeleteValue(hKey, mszDllPaths[i]);
  360. }
  361. else
  362. {
  363. //
  364. // Set the value to its new count.
  365. //
  366. if (ERROR_SUCCESS != RegSetValueEx(hKey, mszDllPaths[i], 0, REG_DWORD,
  367. (LPBYTE)&dwCount, sizeof(DWORD)))
  368. {
  369. hr = S_FALSE;
  370. }
  371. //
  372. // If we are incrementing the count then we should register the dll.
  373. //
  374. if (bIncrement)
  375. {
  376. hr = RegisterDll(mszDllPaths[i]);
  377. }
  378. }
  379. }
  380. RegCloseKey(hKey);
  381. }
  382. /// TraceError("RefCountPbaSharedDlls", hr);
  383. return hr;
  384. }
  385. //+---------------------------------------------------------------------------
  386. //
  387. // Function: UnregisterAndDeleteDll
  388. //
  389. // Purpose: Unregister and delete the given COM component
  390. //
  391. // Arguments: pszFile -- The full path to the file to unregister and delete
  392. //
  393. //
  394. // Returns: S_OK if successfull, Win32 error otherwise.
  395. //
  396. // Author: quintinb 9 OCT 1998
  397. //
  398. // Notes:
  399. //
  400. HRESULT UnregisterAndDeleteDll(PCSTR pszFile)
  401. {
  402. HINSTANCE hLib = NULL;
  403. FARPROC pfncUnRegister;
  404. HRESULT hr = S_OK;
  405. if ((NULL == pszFile) || (L'\0' == pszFile[0]))
  406. {
  407. return E_INVALIDARG;
  408. }
  409. hLib = LoadLibrary(pszFile);
  410. if (NULL != hLib)
  411. {
  412. pfncUnRegister = GetProcAddress(hLib, "DllUnregisterServer");
  413. if (NULL != pfncUnRegister)
  414. {
  415. hr = (HRESULT)(pfncUnRegister)();
  416. if (SUCCEEDED(hr))
  417. {
  418. FreeLibrary(hLib);
  419. hLib = NULL;
  420. // You can add this back in as long as you are sure that we copied the file down and thus
  421. // should be deleting it when the ref count is Zero.
  422. // This was removed because PBA setup is moving to Value Add and because of bug 323231
  423. // if (!DeleteFile(pszFile))
  424. // {
  425. // hr = S_FALSE;
  426. // }
  427. }
  428. }
  429. else
  430. {
  431. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  432. }
  433. }
  434. else
  435. {
  436. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  437. }
  438. if (NULL != hLib)
  439. {
  440. FreeLibrary(hLib);
  441. }
  442. /// TraceError("UnregisterAndDeleteDll", hr);
  443. return hr;
  444. }
  445. //+---------------------------------------------------------------------------
  446. //
  447. // Function: RegisterDll
  448. //
  449. // Purpose: Register the given COM component
  450. //
  451. // Arguments: pszFile -- The full path to the file to register
  452. //
  453. //
  454. // Returns: S_OK if successfull, Win32 error otherwise.
  455. //
  456. // Author: quintinb 9 OCT 1998
  457. //
  458. // Notes:
  459. //
  460. HRESULT RegisterDll(PCSTR pszFile)
  461. {
  462. HINSTANCE hLib = NULL;
  463. FARPROC pfncRegister;
  464. HRESULT hr = S_OK;
  465. if ((NULL == pszFile) || (L'\0' == pszFile[0]))
  466. {
  467. return E_INVALIDARG;
  468. }
  469. hLib = LoadLibrary(pszFile);
  470. if (NULL != hLib)
  471. {
  472. pfncRegister = GetProcAddress(hLib, "DllRegisterServer");
  473. if (NULL != pfncRegister)
  474. {
  475. hr = (HRESULT)(pfncRegister)();
  476. }
  477. else
  478. {
  479. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  480. }
  481. }
  482. else
  483. {
  484. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  485. }
  486. if (NULL != hLib)
  487. {
  488. FreeLibrary(hLib);
  489. }
  490. /// TraceError("RegisterDll", hr);
  491. return hr;
  492. }
  493. //+----------------------------------------------------------------------------
  494. //
  495. // Function: InstallPBA
  496. //
  497. // Synopsis: This function is responsible for installing PBA
  498. //
  499. // Arguments: HINSTANCE hInstance - Exe Instance handle for resources
  500. // LPCTSTR szInfPath - Path of the INF to install from
  501. //
  502. // Returns: BOOL - returns TRUE if successful.
  503. //
  504. // History: v-vijayb Created Header 5/25/99
  505. //
  506. //+----------------------------------------------------------------------------
  507. BOOL InstallPBA(HINSTANCE hInstance, LPCSTR szInfPath)
  508. {
  509. BOOL fInstalled = FALSE;
  510. TCHAR szTemp[MAX_PATH+1];
  511. //
  512. // Check to see that these files exist
  513. //
  514. if (!FileExists(szInfPath))
  515. {
  516. wsprintf(szTemp, TEXT("InstallPBA, unable to find %s"), szInfPath);
  517. MessageBox(NULL, szTemp, g_szAppTitle, MB_OK);
  518. return (FALSE);
  519. }
  520. if (HrGetPbaInstallPath(szTemp, sizeof(szTemp)) == S_OK)
  521. {
  522. HKEY hKey;
  523. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, 0, "",
  524. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  525. {
  526. RegSetValueEx(hKey, "PBAPath", 0, REG_SZ, (PBYTE) szTemp, lstrlen(szTemp) + sizeof(TCHAR));
  527. RegCloseKey(hKey);
  528. }
  529. }
  530. MYVERIFY(SUCCEEDED(LaunchInfSection(szInfPath, TEXT("DefaultInstall"), g_szAppTitle, 0)));
  531. RefCountPbaSharedDlls(TRUE);
  532. fInstalled = TRUE;
  533. return (fInstalled);
  534. } // InstallPBA()
  535. //+----------------------------------------------------------------------------
  536. //
  537. // Function: UnInstallPBA
  538. //
  539. // Synopsis: This function is responsible for uninstalling PBA
  540. //
  541. // Arguments: HINSTANCE hInstance - Exe Instance handle for resources
  542. // LPCTSTR szInfPath - Path of the INF to install from
  543. //
  544. // Returns: BOOL - returns TRUE if successful.
  545. //
  546. // History: v-vijayb Created Header 5/25/99
  547. //
  548. //+----------------------------------------------------------------------------
  549. BOOL UninstallPBA(HINSTANCE hInstance, LPCSTR szInfPath)
  550. {
  551. BOOL fUninstalled = FALSE;
  552. TCHAR szTemp[MAX_PATH+1];
  553. //
  554. // Check to see that these files exist
  555. //
  556. if (!FileExists(szInfPath))
  557. {
  558. wsprintf(szTemp, TEXT("UninstallPBA, unable to find %s"), szInfPath);
  559. MessageBox(NULL, szTemp, g_szAppTitle, MB_OK);
  560. return (FALSE);
  561. }
  562. MYVERIFY(SUCCEEDED(LaunchInfSection(szInfPath, TEXT("Uninstall"), g_szAppTitle, 0)));
  563. RefCountPbaSharedDlls(FALSE);
  564. fUninstalled = TRUE;
  565. return (fUninstalled);
  566. } // UninstallPBA()