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

//+----------------------------------------------------------------------------
//
// File: pbasetup.cpp
//
// Module: PBASETUP.EXE
//
// Synopsis: PBA stand alone installer for ValueAdd
//
// Copyright (c) 1999 Microsoft Corporation
//
// Author: v-vijayb Created 05/25/99
//
//+----------------------------------------------------------------------------
#include "pbamaster.h"
#include "cmplat.h"
// This is really ugly, we need to consolidate our platform detection code between CM and
// the setup components.
BOOL IsAtLeastNT5()
{
CPlatform plat;
return plat.IsAtLeastNT5();
}
#define OS_NT5 (IsAtLeastNT5())
#include "MemberOfGroup.cpp"
TCHAR g_szAppTitle[MAX_PATH]; // global buffer for app. title
const TCHAR* const c_pszPBAStpMutex = TEXT("Phone Book Administration Installer");
HRESULT UnregisterAndDeleteDll(PCSTR pszFile);;
HRESULT RegisterDll(PCSTR pszFile);
BOOL UninstallPBA(HINSTANCE hInstance, LPCSTR szInfPath);
BOOL IsAdmin(void);
int WINAPI WinMain (HINSTANCE, // hInstance
HINSTANCE, //hPrevInstance
PSTR, // szCmdLine
int) //iCmdShow
{
HINSTANCE hInstance = GetModuleHandleA(NULL);
TCHAR szMsg[MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szInfPath[MAX_PATH+1];
TCHAR szCurrentDir[MAX_PATH+1];
DWORD idMsgEnd;
DWORD dwFlags;
CPlatform pPlatForm;
LPTSTR pszCommandLine;
const DWORD c_dwNormal = 0;
TCHAR c_pszUninstallMode[] = TEXT("/u");
const DWORD c_dwUninstallMode = 0x1;
BOOL bUsageError = FALSE;
BOOL bAnotherInstanceRunning = FALSE;
const int c_NumArgs = 1;
MYVERIFY(0 != LoadString(hInstance, IDS_APP_TITLE, g_szAppTitle, MAX_PATH));
if (!pPlatForm.IsAtLeastNT5())
{
MYVERIFY(0 != LoadString(hInstance, IDS_NOT_NT5, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
return (-1);
}
//
// check that the user has sufficient permissions
//
if (!IsAdmin())
{
MYVERIFY(0 != LoadString(hInstance, IDS_NOPERMS_MSG, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
return (-1);
}
//
// Get the Command Line
//
pszCommandLine = GetCommandLine();
//
// Setup the Class to process the command line args
//
ZeroMemory(szTemp, sizeof(szTemp));
ZeroMemory(szInfPath, sizeof(szInfPath));
ArgStruct Args[c_NumArgs];
Args[0].pszArgString = c_pszUninstallMode;
Args[0].dwFlagModifier = c_dwUninstallMode;
{ // Make sure ArgProcessor gets destructed properly and we don't leak mem
CProcessCmdLn ArgProcessor(c_NumArgs, (ArgStruct*)Args, TRUE,
TRUE); //bSkipFirstToken == TRUE, bBlankCmdLnOkay == TRUE
if (ArgProcessor.GetCmdLineArgs(pszCommandLine, &dwFlags, szTemp, MAX_PATH))
{
CNamedMutex CmPBAMutex;
if (CmPBAMutex.Lock(c_pszPBAStpMutex, FALSE, 0))
{
//
// We got the mutex lock, so Construct the Inf Paths and continue.
// Note that we don't use any file arguments passed into cmakstp.
// It is setup to do so, but we don't need it.
//
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szCurrentDir));
MYVERIFY(CELEMS(szInfPath) > (UINT)wsprintf(szInfPath, TEXT("%s\\pbasetup.inf"), szCurrentDir));
if (c_dwNormal == dwFlags)
{
if (InstallPBA(hInstance, szInfPath))
{
MYVERIFY(0 != LoadString(hInstance, IDS_SUCCESSFUL, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
}
}
else if (c_dwUninstallMode & dwFlags)
{
// Confirm if the user wants to remove the program
MYVERIFY(0 != LoadString(hInstance, IDS_REMOVEPBA, szMsg, MAX_PATH));
if (MessageBox(NULL, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND) != IDYES)
{
ExitProcess(0);
return (0);
}
if (UninstallPBA(hInstance, szTemp))
{
MYVERIFY(0 != LoadString(hInstance, IDS_REMOVESUCCESSFUL, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
}
}
else
{
//
// unsupported switch
//
bUsageError = TRUE;
}
}
else
{
bAnotherInstanceRunning = TRUE;
}
}
else
{
bUsageError = TRUE;
}
}
if (bUsageError)
{
MYVERIFY(0 != LoadString(hInstance, IDS_USAGE_MSG, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
}
else if (bAnotherInstanceRunning)
{
MYVERIFY(0 != LoadString(hInstance, IDS_INUSE_MSG, szMsg, MAX_PATH));
MessageBox(NULL, szMsg, g_szAppTitle, MB_OK);
}
ExitProcess(0);
return (0);
}
const TCHAR* const c_szDaoClientsPath = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\DAO\\Clients");
const TCHAR* c_szMSSharedDAO360Path = TEXT("Microsoft Shared\\DAO");
const TCHAR* c_szCommonFilesDir = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
//+---------------------------------------------------------------------------
//
// Function: HrGetPbaInstallPath
//
// Purpose: Get the install path for pbadmin.exe.
//
// Arguments: pszCpaPath -- buffer to hold the install path of PBA.
// dwNumChars -- the number of characters that the buffer can hold.
//
//
// Returns: S_OK if successfull, Win32 error otherwise.
//
// Author: quintinb 19 OCT 1998
//
// Notes:
//
HRESULT HrGetPbaInstallPath(PTCHAR pszCpaPath, DWORD dwNumChars)
{
HRESULT hr = E_FAIL;
HKEY hKey;
BOOL bFound = FALSE;
DWORD lError;
// We need to setup the custom DIRID so that CPA will install
// to the correct location. First get the path from the system.
//
ZeroMemory(pszCpaPath, sizeof(TCHAR)*dwNumChars);
lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, 0, KEY_READ, &hKey);
if (lError == ERROR_SUCCESS)
{
TCHAR szCurrentValue[MAX_PATH+1];
TCHAR szCurrentData[MAX_PATH+1];
DWORD dwValueSize = MAX_PATH;
DWORD dwDataSize = MAX_PATH;
DWORD dwType;
DWORD dwIndex = 0;
hr = S_OK;
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
(LPBYTE)szCurrentData, &dwDataSize))
{
_strlwr(szCurrentValue);
if (NULL != strstr(szCurrentValue, TEXT("pbadmin.exe")))
{
//
// Then we have found the PBA path
//
TCHAR* pszTemp = strrchr(szCurrentValue, '\\');
if (NULL != pszTemp)
{
*pszTemp = L'\0';
lstrcpy(pszCpaPath, szCurrentValue);
bFound = TRUE;
break;
}
}
dwValueSize = MAX_PATH;
dwDataSize = MAX_PATH;
dwIndex++;
}
RegCloseKey(hKey);
}
if (!bFound)
{
BOOL bTmp;
// This is a fresh install of PBA, don't return an error
//
bTmp = SHGetSpecialFolderPath(NULL, pszCpaPath, CSIDL_PROGRAM_FILES, FALSE);
if (bTmp)
{
lstrcat(pszCpaPath, TEXT("\\PBA"));
hr = S_OK;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: RefCountPbaSharedDlls
//
// Purpose: Reference count and register/unregister all of the PBAdmin
// shared components.
//
// Arguments: BOOL bIncrement -- if TRUE, then increment the ref count,
// else decrement it
//
//
// Returns: S_OK if successfull, Win32 error otherwise.
//
// Author: quintinb 9 OCT 1998
//
// Notes:
//
HRESULT RefCountPbaSharedDlls(BOOL bIncrement)
{
HRESULT hr = S_OK;
HKEY hKey;
TCHAR szSystemDir[MAX_PATH+1];
TCHAR szDaoPath[MAX_PATH+1], szCommonFilesPath[MAX_PATH+1];
DWORD dwSize;
DWORD dwCount;
LONG lResult;
const UINT uNumDlls = 5;
const UINT uStringLen = 12 + 1;
const TCHAR* const c_szSsFmt = TEXT("%s\\%s");
const TCHAR* const c_szSharedDllsPath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDlls");
TCHAR mszDlls[uNumDlls][uStringLen] = { "comctl32.ocx",
"comdlg32.ocx",
"msinet.ocx",
"tabctl32.ocx",
"dao360.dll"
};
TCHAR mszDllPaths[uNumDlls][MAX_PATH];
//
// All of the Dlls that we ref count are in the system directory, except for Dao350.dll.
// Thus we want to append the system directory path to our filenames and handle dao last.
//
if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
{
return E_UNEXPECTED;
}
for (int i = 0; i < (uNumDlls-1) ; i++)
{
wsprintf(mszDllPaths[i], c_szSsFmt, szSystemDir, mszDlls[i]);
}
//
// Now write out the dao360.dll path.
//
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szCommonFilesDir, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize))
{
dwSize = sizeof(szCommonFilesPath);
lResult = RegQueryValueEx(hKey, TEXT("CommonFilesDir"), NULL, NULL,(LPBYTE)szCommonFilesPath, &dwSize);
RegCloseKey(hKey);
}
if (ERROR_SUCCESS != lResult)
{
_tcscpy(szCommonFilesPath, TEXT("c:\\Program Files\\Common Files"));
}
wsprintf(szDaoPath, TEXT("%s\\%s"), szCommonFilesPath, c_szMSSharedDAO360Path);
wsprintf(mszDllPaths[i], c_szSsFmt, szDaoPath, mszDlls[i]);
//
// Open the shared DLL key and start enumerating our multi-sz with all of our dll's
// to add.
//
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szSharedDllsPath,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize)) // using dwSize as a temp to hold the disposition value
{
for (int i=0; i < uNumDlls; i++)
{
dwSize = sizeof(DWORD);
lResult = RegQueryValueEx(hKey, mszDllPaths[i], NULL, NULL,(LPBYTE)&dwCount, &dwSize);
if (ERROR_SUCCESS == lResult)
{
//
// Increment or decrement as appropriate. Make sure not to decrement 0
//
if (0 != dwCount || bIncrement)
{
dwCount = dwCount + (bIncrement ? 1 : -1);
}
}
else if (ERROR_FILE_NOT_FOUND == lResult)
{
if (bIncrement)
{
//
// The the value doesn't yet exist. Set the count to 1.
//
dwCount = 1;
}
else
{
//
// We are decrementing and we couldn't find the DLL, nothing to
// change for the count but we should still delete the dll.
//
dwCount = 0;
}
}
else
{
hr = S_FALSE;
continue;
}
//
// Not that we have determined the ref count, do something about it.
//
if (dwCount == 0)
{
//
// We don't want to delete dao350.dll, but otherwise we need to delete
// the file if it has a zero refcount.
//
if (CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, mszDlls[i], -1, TEXT("dao360.dll"), -1))
{
hr = UnregisterAndDeleteDll(mszDllPaths[i]);
if (FAILED(hr))
{
//
// Don't fail the setup over a file that we couldn't unregister or
// couldn't delete
//
hr = S_FALSE;
}
}
RegDeleteValue(hKey, mszDllPaths[i]);
}
else
{
//
// Set the value to its new count.
//
if (ERROR_SUCCESS != RegSetValueEx(hKey, mszDllPaths[i], 0, REG_DWORD,
(LPBYTE)&dwCount, sizeof(DWORD)))
{
hr = S_FALSE;
}
//
// If we are incrementing the count then we should register the dll.
//
if (bIncrement)
{
hr = RegisterDll(mszDllPaths[i]);
}
}
}
RegCloseKey(hKey);
}
/// TraceError("RefCountPbaSharedDlls", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: UnregisterAndDeleteDll
//
// Purpose: Unregister and delete the given COM component
//
// Arguments: pszFile -- The full path to the file to unregister and delete
//
//
// Returns: S_OK if successfull, Win32 error otherwise.
//
// Author: quintinb 9 OCT 1998
//
// Notes:
//
HRESULT UnregisterAndDeleteDll(PCSTR pszFile)
{
HINSTANCE hLib = NULL;
FARPROC pfncUnRegister;
HRESULT hr = S_OK;
if ((NULL == pszFile) || (L'\0' == pszFile[0]))
{
return E_INVALIDARG;
}
hLib = LoadLibrary(pszFile);
if (NULL != hLib)
{
pfncUnRegister = GetProcAddress(hLib, "DllUnregisterServer");
if (NULL != pfncUnRegister)
{
hr = (HRESULT)(pfncUnRegister)();
if (SUCCEEDED(hr))
{
FreeLibrary(hLib);
hLib = NULL;
// You can add this back in as long as you are sure that we copied the file down and thus
// should be deleting it when the ref count is Zero.
// This was removed because PBA setup is moving to Value Add and because of bug 323231
// if (!DeleteFile(pszFile))
// {
// hr = S_FALSE;
// }
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
if (NULL != hLib)
{
FreeLibrary(hLib);
}
/// TraceError("UnregisterAndDeleteDll", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: RegisterDll
//
// Purpose: Register the given COM component
//
// Arguments: pszFile -- The full path to the file to register
//
//
// Returns: S_OK if successfull, Win32 error otherwise.
//
// Author: quintinb 9 OCT 1998
//
// Notes:
//
HRESULT RegisterDll(PCSTR pszFile)
{
HINSTANCE hLib = NULL;
FARPROC pfncRegister;
HRESULT hr = S_OK;
if ((NULL == pszFile) || (L'\0' == pszFile[0]))
{
return E_INVALIDARG;
}
hLib = LoadLibrary(pszFile);
if (NULL != hLib)
{
pfncRegister = GetProcAddress(hLib, "DllRegisterServer");
if (NULL != pfncRegister)
{
hr = (HRESULT)(pfncRegister)();
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
if (NULL != hLib)
{
FreeLibrary(hLib);
}
/// TraceError("RegisterDll", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Function: InstallPBA
//
// Synopsis: This function is responsible for installing PBA
//
// Arguments: HINSTANCE hInstance - Exe Instance handle for resources
// LPCTSTR szInfPath - Path of the INF to install from
//
// Returns: BOOL - returns TRUE if successful.
//
// History: v-vijayb Created Header 5/25/99
//
//+----------------------------------------------------------------------------
BOOL InstallPBA(HINSTANCE hInstance, LPCSTR szInfPath)
{
BOOL fInstalled = FALSE;
TCHAR szTemp[MAX_PATH+1];
//
// Check to see that these files exist
//
if (!FileExists(szInfPath))
{
wsprintf(szTemp, TEXT("InstallPBA, unable to find %s"), szInfPath);
MessageBox(NULL, szTemp, g_szAppTitle, MB_OK);
return (FALSE);
}
if (HrGetPbaInstallPath(szTemp, sizeof(szTemp)) == S_OK)
{
HKEY hKey;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, 0, "",
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
RegSetValueEx(hKey, "PBAPath", 0, REG_SZ, (PBYTE) szTemp, lstrlen(szTemp) + sizeof(TCHAR));
RegCloseKey(hKey);
}
}
MYVERIFY(SUCCEEDED(LaunchInfSection(szInfPath, TEXT("DefaultInstall"), g_szAppTitle, 0)));
RefCountPbaSharedDlls(TRUE);
fInstalled = TRUE;
return (fInstalled);
} // InstallPBA()
//+----------------------------------------------------------------------------
//
// Function: UnInstallPBA
//
// Synopsis: This function is responsible for uninstalling PBA
//
// Arguments: HINSTANCE hInstance - Exe Instance handle for resources
// LPCTSTR szInfPath - Path of the INF to install from
//
// Returns: BOOL - returns TRUE if successful.
//
// History: v-vijayb Created Header 5/25/99
//
//+----------------------------------------------------------------------------
BOOL UninstallPBA(HINSTANCE hInstance, LPCSTR szInfPath)
{
BOOL fUninstalled = FALSE;
TCHAR szTemp[MAX_PATH+1];
//
// Check to see that these files exist
//
if (!FileExists(szInfPath))
{
wsprintf(szTemp, TEXT("UninstallPBA, unable to find %s"), szInfPath);
MessageBox(NULL, szTemp, g_szAppTitle, MB_OK);
return (FALSE);
}
MYVERIFY(SUCCEEDED(LaunchInfSection(szInfPath, TEXT("Uninstall"), g_szAppTitle, 0)));
RefCountPbaSharedDlls(FALSE);
fUninstalled = TRUE;
return (fUninstalled);
} // UninstallPBA()