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.
791 lines
21 KiB
791 lines
21 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// File: NCNetCPA.CPP
|
|
//
|
|
// Module: NetOC.DLL
|
|
//
|
|
// Synopsis: Implements the dll entry points required to integrate into
|
|
// NetOC.DLL the installation of the following components.
|
|
//
|
|
// NETCPS
|
|
//
|
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Author: Anas Jarrah (a-anasj) Created 3/9/98
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include <atlbase.h>
|
|
extern CComModule _Module;
|
|
#include <atlcom.h>
|
|
#include "ncatl.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "nccm.h"
|
|
|
|
//
|
|
// Define Globals
|
|
//
|
|
WCHAR g_szCpaPath[MAX_PATH+1];
|
|
WCHAR g_szDaoPath[MAX_PATH+1];
|
|
|
|
//
|
|
// Define Constants
|
|
//
|
|
const DWORD c_dwCpaDirID = 123176; // just must be larger than DIRID_USER = 0x8000;
|
|
const DWORD c_dwDaoDirID = 123177; // just must be larger than DIRID_USER = 0x8000;
|
|
|
|
const WCHAR* const c_szDaoClientsPath = L"SOFTWARE\\Microsoft\\Shared Tools\\DAO\\Clients";
|
|
const WCHAR* const c_szCommonFilesPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion";
|
|
const WCHAR* const c_szCommonFilesDirValue = L"CommonFilesDir";
|
|
|
|
HRESULT HrGetPBAPathIfInstalled(PWSTR pszCpaPath, DWORD dwNumChars)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey;
|
|
BOOL bFound = FALSE;
|
|
|
|
// We need to see if PBA is installed or not. If it is then we want to
|
|
// add back the PBA start menu link. If it isn't, then we want to do nothing
|
|
// with PBA.
|
|
//
|
|
|
|
ZeroMemory(pszCpaPath, sizeof(WCHAR)*dwNumChars);
|
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, KEY_READ, &hKey);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR szCurrentValue[MAX_PATH+1];
|
|
WCHAR szCurrentData[MAX_PATH+1];
|
|
DWORD dwValueSize = MAX_PATH;
|
|
DWORD dwDataSize = MAX_PATH;
|
|
DWORD dwType;
|
|
DWORD dwIndex = 0;
|
|
|
|
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
|
|
(LPBYTE)szCurrentData, &dwDataSize))
|
|
{
|
|
_wcslwr(szCurrentValue);
|
|
if (NULL != wcsstr(szCurrentValue, L"pbadmin.exe"))
|
|
{
|
|
//
|
|
// Then we have found the PBA path
|
|
//
|
|
|
|
WCHAR* pszTemp = wcsrchr(szCurrentValue, L'\\');
|
|
if (NULL != pszTemp)
|
|
{
|
|
*pszTemp = L'\0';
|
|
lstrcpyW(pszCpaPath, szCurrentValue);
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
dwValueSize = MAX_PATH;
|
|
dwDataSize = MAX_PATH;
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
// We didn't find PBA, so lets return S_FALSE
|
|
//
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL GetAdminToolsFolder(PWSTR pszAdminTools)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
if (pszAdminTools)
|
|
{
|
|
bReturn = SHGetSpecialFolderPath(NULL, pszAdminTools, CSIDL_COMMON_PROGRAMS, TRUE);
|
|
|
|
if (bReturn)
|
|
{
|
|
// Now Append Administrative Tools
|
|
//
|
|
lstrcat(pszAdminTools, SzLoadIds(IDS_OC_ADMIN_TOOLS));
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
HRESULT HrCreatePbaShortcut(PWSTR pszCpaPath)
|
|
{
|
|
HRESULT hr = CoInitialize(NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IShellLink *psl = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_ShellLink, NULL,
|
|
CLSCTX_INPROC_SERVER, //CLSCTX_LOCAL_SERVER,
|
|
IID_IShellLink,
|
|
(LPVOID*)&psl);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPersistFile *ppf = NULL;
|
|
|
|
// Set up the properties of the Shortcut
|
|
//
|
|
static const WCHAR c_szPbAdmin[] = L"\\pbadmin.exe";
|
|
|
|
WCHAR szPathToPbadmin[MAX_PATH+1] = {0};
|
|
DWORD dwLen = lstrlen(c_szPbAdmin) + lstrlen(pszCpaPath) + 1;
|
|
|
|
if (MAX_PATH >= dwLen)
|
|
{
|
|
// Set the Path to pbadmin.exe
|
|
//
|
|
lstrcpy(szPathToPbadmin, pszCpaPath);
|
|
lstrcat(szPathToPbadmin, c_szPbAdmin);
|
|
|
|
hr = psl->SetPath(szPathToPbadmin);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Set the Description to Phone Book Administrator
|
|
//
|
|
hr = psl->SetDescription(SzLoadIds(IDS_OC_PBA_DESC));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psl->QueryInterface(IID_IPersistFile,
|
|
(LPVOID *)&ppf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR szAdminTools[MAX_PATH+1] = {0};
|
|
if (GetAdminToolsFolder(szAdminTools))
|
|
{
|
|
// Create the link file.
|
|
//
|
|
hr = ppf->Save(szAdminTools, TRUE);
|
|
}
|
|
|
|
ReleaseObj(ppf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj(psl);
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrOcCpaPreQueueFiles
|
|
//
|
|
// Purpose: Called by optional components installer code to handle
|
|
// additional installation requirements for PhoneBook Server.
|
|
//
|
|
// Arguments:
|
|
// pnocd [in] Pointer to NETOC data.
|
|
//
|
|
// Returns: S_OK if successfull, Win32 error otherwise.
|
|
//
|
|
// Author: quintinb 18 Sep 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT HrOcCpaPreQueueFiles(PNETOCDATA pnocd)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch ( pnocd->eit )
|
|
{
|
|
case IT_UPGRADE:
|
|
|
|
WCHAR szPbaInstallPath[MAX_PATH+1];
|
|
|
|
hr = HrGetPBAPathIfInstalled(szPbaInstallPath, MAX_PATH);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
HrCreatePbaShortcut(szPbaInstallPath);
|
|
}
|
|
|
|
break;
|
|
|
|
case IT_INSTALL:
|
|
case IT_REMOVE:
|
|
|
|
break;
|
|
}
|
|
|
|
TraceError("HrOcCpaPreQueueFiles", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrOcCpaPreQueueFiles
|
|
//
|
|
// Purpose: Called by optional components installer code to handle
|
|
// additional installation requirements for PhoneBook Server.
|
|
//
|
|
// Arguments:
|
|
// pnocd [in] Pointer to NETOC data.
|
|
//
|
|
// Returns: S_OK if successfull, Win32 error otherwise.
|
|
//
|
|
// Author: quintinb 18 Sep 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT HrOcCpaPreQueueFiles(PNETOCDATA pnocd)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch ( pnocd->eit )
|
|
{
|
|
case IT_UPGRADE:
|
|
case IT_INSTALL:
|
|
case IT_REMOVE:
|
|
|
|
//
|
|
// Get the PBA install Dir.
|
|
//
|
|
hr = HrGetPbaInstallPath(g_szCpaPath, celems(g_szCpaPath));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Next Create the CPA Dir ID
|
|
//
|
|
hr = HrEnsureInfFileIsOpen(pnocd->pszComponentId, *pnocd);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if(!SetupSetDirectoryId(pnocd->hinfFile, c_dwCpaDirID, g_szCpaPath))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now query the system for the DAO350 install path
|
|
//
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
hr = HrGetDaoInstallPath(g_szDaoPath, celems(g_szDaoPath));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Next Create the DAO Dir ID
|
|
//
|
|
hr = HrEnsureInfFileIsOpen(pnocd->pszComponentId, *pnocd);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if(!SetupSetDirectoryId(pnocd->hinfFile, c_dwDaoDirID, g_szDaoPath))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
TraceError("HrOcCpaPreQueueFiles", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrOcCpaOnInstall
|
|
//
|
|
// Purpose: Called by optional components installer code to handle
|
|
// additional installation requirements for PhoneBook Server.
|
|
//
|
|
// Arguments:
|
|
// pnocd [in] Pointer to NETOC data.
|
|
//
|
|
// Returns: S_OK if successfull, Win32 error otherwise.
|
|
//
|
|
// Author: quintinb 18 Sep 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT HrOcCpaOnInstall(PNETOCDATA pnocd)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
switch ( pnocd->eit )
|
|
{
|
|
case IT_INSTALL:
|
|
hr = RefCountPbaSharedDlls(TRUE); // bIncrement = TRUE
|
|
break;
|
|
|
|
case IT_REMOVE:
|
|
hr = RefCountPbaSharedDlls(FALSE); // bIncrement = FALSE
|
|
break;
|
|
|
|
case IT_UPGRADE:
|
|
DeleteOldNtopLinks();
|
|
break;
|
|
|
|
case IT_UNKNOWN:
|
|
case IT_NO_CHANGE:
|
|
break;
|
|
}
|
|
|
|
TraceError("HrOcCpaOnInstall", hr);
|
|
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;
|
|
WCHAR szSystemDir[MAX_PATH+1];
|
|
DWORD dwSize;
|
|
DWORD dwCount;
|
|
LONG lResult;
|
|
const UINT uNumDlls = 6;
|
|
const UINT uStringLen = 12 + 1;
|
|
const WCHAR* const c_szSsFmt = L"%s\\%s";
|
|
const WCHAR* const c_szSharedDllsPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDlls";
|
|
WCHAR mszDlls[uNumDlls][uStringLen] = { L"comctl32.ocx",
|
|
L"comdlg32.ocx",
|
|
L"msinet.ocx",
|
|
L"tabctl32.ocx",
|
|
L"dbgrid32.ocx",
|
|
L"dao350.dll"
|
|
};
|
|
|
|
WCHAR 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++)
|
|
{
|
|
wsprintfW(mszDllPaths[i], c_szSsFmt, szSystemDir, mszDlls[i]);
|
|
}
|
|
|
|
//
|
|
// Now write out the dao350.dll path.
|
|
//
|
|
wsprintfW(mszDllPaths[i], c_szSsFmt, g_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 = RegQueryValueExW(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 (0 != lstrcmpiW(mszDlls[i], L"dao350.dll"))
|
|
{
|
|
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(PCWSTR 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 = (pfncUnRegister)();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
FreeLibrary(hLib);
|
|
hLib = NULL;
|
|
// 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(PCWSTR 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 = (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: 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(PWSTR pszCpaPath, DWORD dwNumChars)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey;
|
|
BOOL bFound = FALSE;
|
|
|
|
// 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(WCHAR)*dwNumChars);
|
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDaoClientsPath, KEY_READ, &hKey);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR szCurrentValue[MAX_PATH+1];
|
|
WCHAR szCurrentData[MAX_PATH+1];
|
|
DWORD dwValueSize = MAX_PATH;
|
|
DWORD dwDataSize = MAX_PATH;
|
|
DWORD dwType;
|
|
DWORD dwIndex = 0;
|
|
|
|
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
|
|
(LPBYTE)szCurrentData, &dwDataSize))
|
|
{
|
|
_wcslwr(szCurrentValue);
|
|
if (NULL != wcsstr(szCurrentValue, L"pbadmin.exe"))
|
|
{
|
|
//
|
|
// Then we have found the PBA path
|
|
//
|
|
|
|
WCHAR* pszTemp = wcsrchr(szCurrentValue, L'\\');
|
|
if (NULL != pszTemp)
|
|
{
|
|
*pszTemp = L'\0';
|
|
lstrcpyW(pszCpaPath, szCurrentValue);
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
dwValueSize = MAX_PATH;
|
|
dwDataSize = MAX_PATH;
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
// This is a fresh install of CPA, don't return an error
|
|
//
|
|
hr = SHGetSpecialFolderPath(NULL, pszCpaPath, CSIDL_PROGRAM_FILES, FALSE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
lstrcatW(pszCpaPath, L"\\PBA");
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrGetDaoInstallPath
|
|
//
|
|
// 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 HrGetDaoInstallPath(PWSTR pszDaoPath, DWORD dwNumChars)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey;
|
|
|
|
// We need to setup the custom DIRID so that CPA will install
|
|
// to the correct location. First get the path from the system.
|
|
//
|
|
|
|
ZeroMemory(pszDaoPath, sizeof(WCHAR)*dwNumChars);
|
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szCommonFilesPath, KEY_ALL_ACCESS, &hKey);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD dwSize = sizeof(WCHAR)*dwNumChars;
|
|
|
|
//
|
|
// Try to get the CommonFilesDir value from the registry, but if it doesn't exist
|
|
// then create it.
|
|
//
|
|
if (ERROR_SUCCESS != RegQueryValueExW(hKey, c_szCommonFilesDirValue, NULL, NULL,
|
|
(LPBYTE)pszDaoPath, &dwSize))
|
|
{
|
|
hr = SHGetSpecialFolderPath(NULL, pszDaoPath, CSIDL_PROGRAM_FILES, FALSE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// QBBUG -- Common files is localizable. Make a string resource.
|
|
//
|
|
lstrcatW(pszDaoPath, (PWSTR)SzLoadIds(IDS_OC_COMMON_FILES));
|
|
|
|
//
|
|
// Now set the regvalue
|
|
//
|
|
hr = HrRegSetValueEx(hKey, c_szCommonFilesDirValue, REG_SZ,
|
|
(const BYTE*)pszDaoPath, sizeof(WCHAR)*dwNumChars);
|
|
}
|
|
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// QBBUG -- should Microsoft shared be a string resource?
|
|
//
|
|
lstrcatW(g_szDaoPath, (PWSTR)SzLoadIds(IDS_OC_MS_SHARED_DAO));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
*/
|