|
|
//////////////////////////////////////////////////////////////////////////////
//
// File Name: fxocUtil.cpp
//
// Abstract: This provides the utility routines used in the FaxOCM
// code base.
//
// Environment: Windows XP / User Mode
//
// Copyright (c) 2000 Microsoft Corporation
//
// Revision History:
//
// Date: Developer: Comments:
// ----- ---------- ---------
// 21-Mar-2000 Oren Rosenbloom (orenr) Created
//////////////////////////////////////////////////////////////////////////////
// Project Includes
#include "faxocm.h"
// System Includes
#include <lmshare.h>
#include <lmaccess.h>
#include <lmerr.h>
#include <Aclapi.h> // For SetSecurityInfo
#pragma hdrstop
//////////////////////// Static Function Prototypes //////////////////////////
///////////////////////////////
// fxocUtil_Init
//
// Initialize the misc. utilities
// required by faxocm.dll.
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise
//
DWORD fxocUtil_Init(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Init Util module"),dwRes);
return dwRes; }
///////////////////////////////
// fxocUtil_Term
//
// Terminate the misc. utilities
// required by faxocm.dll
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocUtil_Term(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Term Util module"),dwRes);
return dwRes; }
///////////////////////////////
// fxocUtil_GetUninstallSection
//
// Get field value in the INF
// pointed to by the INF_KEYWORD_INSTALLTYPE_UNINSTALL
// keyword.
//
// Params:
// - pszSection - section to search for keyword in.
// - pszValue - IN - buffer returning the value of the keyword
// - dwNumBufChars - # of chars the pszValue buffer can hold
//
DWORD fxocUtil_GetUninstallSection(const TCHAR *pszSection, TCHAR *pszValue, DWORD dwNumBufChars) { DWORD dwReturn = NO_ERROR; DBG_ENTER(_T("fxocUtil_GetUninstallSection"),dwReturn,_T("%s"),pszSection);
if ((pszSection == NULL) || (pszValue == NULL) || (dwNumBufChars == 0)) { return ERROR_INVALID_PARAMETER; }
dwReturn = fxocUtil_GetKeywordValue(pszSection, INF_KEYWORD_INSTALLTYPE_UNINSTALL, pszValue, dwNumBufChars); return dwReturn; }
///////////////////////////////
// fxocUtil_GetKeywordValue
//
// This is used for getting the
// various Install/Uninstall
// sections, dependent on if we
// are a clean install, upgrade,
// etc.
//
// The format in the INF will look like this:
//
// [Section]
// Keyword = Value
//
// Params:
// - pszSection - section to search for the keyword in.
// - pszKeyword - keyword to get the value for.
// - pszValue - OUT - buffer that will hold the keyword's value
// - dwNumBufChars - # of characters the pszValue buffer can hold.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocUtil_GetKeywordValue(const TCHAR *pszSection, const TCHAR *pszKeyword, TCHAR *pszValue, DWORD dwNumBufChars) { HINF hInf = faxocm_GetComponentInf(); DWORD dwReturn = NO_ERROR; BOOL bSuccess = FALSE; INFCONTEXT Context;
DBG_ENTER( _T("fxocUtil_GetKeywordValue"), dwReturn, _T("%s - %s "), pszSection, pszKeyword);
if ((pszSection == NULL) || (pszKeyword == NULL) || (pszValue == NULL) || (dwNumBufChars == 0)) { return ERROR_INVALID_PARAMETER; }
bSuccess = ::SetupFindFirstLine(hInf, pszSection, pszKeyword, &Context);
if (bSuccess) { bSuccess = ::SetupGetStringField(&Context, 1, pszValue, dwNumBufChars, NULL);
if (!bSuccess) { dwReturn = ::GetLastError(); VERBOSE(SETUP_ERR, _T("faxocm_GetKeywordValue, failed to get ") _T("keyword value for section '%s', ") _T("keyword '%s', rc = 0x%lx"), pszSection, pszKeyword, dwReturn); } } else { dwReturn = ::GetLastError(); VERBOSE(SETUP_ERR, _T("faxocm_GetKeywordValue, failed to get ") _T("keyword value for component '%s', rc = 0x%lx"), pszSection, dwReturn); }
return dwReturn; }
///////////////////////////////
// fxocUtil_DoSetup
//
// Generic fn to create/delete program links
//
// Params:
// - hInf - handle to INF file
// - pszSection - section to install/uninstall from
// - bInstall - TRUE if installing, FALSE if uninstalling
// - pszFnName - name of calling fn (for debug).
// Returns:
// - NO_ERROR on success
// - error code otherwise.
//
DWORD fxocUtil_DoSetup(HINF hInf, const TCHAR *pszSection, BOOL bInstall, DWORD dwFlags, const TCHAR *pszFnName) { DWORD dwReturn = NO_ERROR; BOOL bSuccess = FALSE;
DBG_ENTER( _T("fxocUtil_DoSetup"), dwReturn, _T("%s - %s "), pszSection, pszFnName);
if ((hInf == NULL) || (pszSection == NULL)) { return ERROR_INVALID_PARAMETER; }
// This function call will install or uninstall the shortcuts depending
// on the value of the "pszSection" parameter. If the section references
// the install section, then the shortcuts will be installed, otherwise
// they will be uninstalled.
bSuccess = ::SetupInstallFromInfSection(NULL, hInf, pszSection, dwFlags, NULL, // relative key root
NULL, // source root path
0, // copy flags
NULL, // callback routine
NULL, // callback routine context
NULL, // device info set
NULL); // device info struct
if (!bSuccess) { dwReturn = ::GetLastError();
VERBOSE(SETUP_ERR, _T("SetupInstallFromInfSection failed, rc = 0x%lx"), dwReturn); }
return dwReturn; }
//////////////////////////////////
// fxocUtil_CreateNetworkShare
//
//
// Create share on the current machine.
// If the share name is already exist,
// then the function will try to erase the share
// and then create new one to lpctstrPath
//
// Params:
// - const FAX_SHARE_Description* fsdShare - share description
// Returns:
// - Returns TRUE on success
// - FALSE otherwise
//
BOOL fxocUtil_CreateNetworkShare(const FAX_SHARE_Description* fsdShare) { SHARE_INFO_502 ShareInfo502; NET_API_STATUS rVal = 0; DWORD dwShareType = 0; DWORD dwNumChars = 0;
WCHAR szExpandedPath[MAX_PATH*2];
DBG_ENTER(_T("fxocUtil_CreateNetworkShare"));
ZeroMemory(&ShareInfo502, sizeof(SHARE_INFO_502));
dwNumChars = ExpandEnvironmentStrings(fsdShare->szPath, szExpandedPath, sizeof(szExpandedPath)/sizeof(szExpandedPath[0])); if (dwNumChars == 0) { VERBOSE(SETUP_ERR, _T("ExpandEnvironmentStrings failed, rc = 0x%lx"), ::GetLastError());
return FALSE; }
ShareInfo502.shi502_netname = (LPTSTR)fsdShare->szName; ShareInfo502.shi502_type = STYPE_DISKTREE; ShareInfo502.shi502_remark = (LPTSTR)fsdShare->szComment; ShareInfo502.shi502_permissions = ACCESS_ALL; ShareInfo502.shi502_max_uses = (DWORD) -1, ShareInfo502.shi502_current_uses = (DWORD) -1; ShareInfo502.shi502_path = szExpandedPath; ShareInfo502.shi502_passwd = NULL; ShareInfo502.shi502_security_descriptor = fsdShare->pSD;
rVal = ::NetShareAdd(NULL, 502, (LPBYTE) &ShareInfo502, NULL);
if (rVal == NERR_Success) { VERBOSE(DBG_MSG, _T("Successfully added '%s' share."), fsdShare->szName); } else if (rVal == NERR_DuplicateShare) { // share by the same name was found, attempt to delete it, and re-add it.
VERBOSE(SETUP_ERR, _T("The share %s already exist, (err=%ld) ") _T("CreateNetworkShare will try to remove the share and ") _T("re-create it."), fsdShare->szName, GetLastError());
// delete duplicate share.
rVal = ::NetShareDel(NULL, (LPTSTR) fsdShare->szName, 0);
VERBOSE(DBG_MSG, _T("NetShareDel returned 0x%lx"), rVal);
if (rVal != NERR_Success) { // failed to delete duplicate share.
VERBOSE(SETUP_ERR, _T("NetShareDel failed to delete '%s' share, rc = 0x%lx,") _T("attempting to recreate it anyway"), fsdShare->szName, rVal); }
// attempt to add new share, even if we failed to delete the duplicate share.
// Hopefully this will work regardless of the delete failure.
rVal = ::NetShareAdd(NULL, 502, (LPBYTE) &ShareInfo502, NULL);
if (rVal == NERR_Success) { VERBOSE(DBG_MSG, _T("Successfully added '%s' share."), fsdShare->szName); } else { VERBOSE(SETUP_ERR, _T("Failed to add '%s' share on second attempt, ") _T("rc = 0x%lx"), rVal);
::SetLastError(rVal); } } else { ::SetLastError(rVal); }
return (rVal == NERR_Success); }
//////////////////////////////////
// fxocUtil_DeleteNetworkShare
//
// Delete a share on the current machine.
// Returns TRUE on success, FALSE otherwise
//
// Params:
// - LPCWSTR lpcwstrShareName : : share name to delete
// Returns:
// - TRUE on Success
// - FALSE otherwise
//
BOOL fxocUtil_DeleteNetworkShare(LPCWSTR pszShareName) { NET_API_STATUS rVal;
DBG_ENTER( _T("fxocUtil_DeleteNetworkShare"), _T("%s"), pszShareName);
rVal = NetShareDel(NULL, // Local computer's share
(LPTSTR) pszShareName, // Name of the share to delete.
0);
return (rVal == NERR_Success); }
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// fxocUtil_SearchAndExecute
//
// Purpose:
// Searches a specified INF section for keywords of the type 'pszSearchKey'
// Each keyword should be in the format 'pszSearchKey' = platform, section to process.
// If the platform matches, then the section is processed according to Flags
// passed to SetupInstallFromInfSection
//
// Params:
// const TCHAR* pszInstallSection - section to search in
// const TCHAR* pszSearchKey - keyword to find
// UINT Flags - flags to pass to SetupInstallFromInfSection
// HSPFILEQ hQueue - handle to file queue, if specified, this function
// will attemp to install files using the
// SetupInstallFilesFromInfSection API
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code - otherwise
//
// Author:
// Mooly Beery (MoolyB) 02-Apr-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD fxocUtil_SearchAndExecute ( const TCHAR* pszInstallSection, const TCHAR* pszSearchKey, UINT Flags, HSPFILEQ hQueue ) { DWORD dwReturn = NO_ERROR; INFCONTEXT Context; BOOL bNextSearchKeyFound = TRUE; HINF hInf = faxocm_GetComponentInf(); DBG_ENTER(_T("fxocUtil_SearchAndExecute"),dwReturn,_T("%s - %s"),pszInstallSection,pszSearchKey);
// let's look for 'pszSearchKey' directives
bNextSearchKeyFound = ::SetupFindFirstLine( hInf, pszInstallSection, pszSearchKey, &Context); if (!bNextSearchKeyFound) { VERBOSE(DBG_WARNING, _T("Did not find '%s' keyword in ") _T("section '%s'. No action will be taken."), pszSearchKey, pszInstallSection);
goto exit; }
while (bNextSearchKeyFound) { // we have a CreateShortcut section.
DWORD dwCount = ::SetupGetFieldCount(&Context); if (dwCount!=2) { VERBOSE(SETUP_ERR,_T("Invalid %s section, has %d param instead of 2"),pszSearchKey,dwCount); goto exit; } // get the platform specifier
INT iPlatform = 0; if (!::SetupGetIntField(&Context, 1, &iPlatform)) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR,_T("SetupGetStringField failed (ec=%d)"),dwReturn); goto exit; } // check the platform we read against the specifier
if (iPlatform & GetProductSKU()) { // we should process this section, get the section name
TCHAR szSectionName[MAX_PATH] = {0}; if (!::SetupGetStringField(&Context,2,szSectionName,MAX_PATH,NULL)) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR,_T("SetupGetStringField failed (ec=%d)"),dwReturn); goto exit; } // check if a file operation was requested
if (hQueue) { if (::SetupInstallFilesFromInfSection(hInf,NULL,hQueue,szSectionName,NULL,Flags)) { VERBOSE(DBG_MSG, _T("Successfully queued files from Section: '%s'"), szSectionName); } else { dwReturn = GetLastError(); VERBOSE(DBG_MSG, _T("Failed to queue files from Section: '%s', Error Code = 0x%lx"), szSectionName, dwReturn); } } else { if (::SetupInstallFromInfSection(NULL,hInf,szSectionName,Flags,NULL,NULL,0,NULL,NULL,NULL,NULL)) { VERBOSE(DBG_MSG, _T("Successfully installed from INF file, section '%s'"), szSectionName); } else { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, _T("Failed to install from INF file, section '%s', dwReturn = 0x%lx"), szSectionName, dwReturn); } } } // get the next section.
bNextSearchKeyFound = ::SetupFindNextMatchLine( &Context, pszSearchKey, &Context); if (!bNextSearchKeyFound) { VERBOSE(DBG_MSG, _T("Did not find '%s' keyword in ") _T("section '%s'. No action will be taken."), pszSearchKey, pszInstallSection); } } exit: return dwReturn; }
/*++
Routine description: Sets security info on a directory
Arguments: lpszFolder [in] - name of directory lpszSD [in] - Desired security descriptor in SDDL format
Return Value: Win32 Error code
Written by: jobarner, 08/2002 --*/ DWORD SetDirSecurity(LPTSTR lpszFolder, LPCTSTR lpszSD) { PSECURITY_DESCRIPTOR pSD = NULL; DWORD ec = ERROR_SUCCESS; DBG_ENTER(_T("SetDirSecurity"),ec);
if (!ConvertStringSecurityDescriptorToSecurityDescriptor( lpszSD, SDDL_REVISION_1, &pSD, NULL)) { ec = GetLastError(); VERBOSE(SETUP_ERR, _T("ConvertStringSecurityDescriptorToSecurityDescriptor Failed, ec=%x"), ec); goto exit; }
//
// Apply the security descriptor recursively to the files.
//
BOOL bDaclPresent = TRUE; BOOL bDaclDefaulted = TRUE; PACL pDacl = NULL;
if(!GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDacl, &bDaclDefaulted) || !bDaclPresent) { ec = GetLastError(); VERBOSE(SETUP_ERR, _T("GetSecurityDescriptorDacl Failed, ec=%x"), ec); goto exit; }
ec = SetNamedSecurityInfo(lpszFolder, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); if (ec != ERROR_SUCCESS) { VERBOSE(SETUP_ERR, _T("SetSecurityInfo Failed, ec=%x"), ec); }
exit: if (pSD) { LocalFree(pSD); } return ec; }
/*++
Routine description: Read dir name from registry and set security info on it
Arguments: lpszKey [in] - name of subkey under HKLM lpszVal [in] - name of value that stores directory name lpszSD [in] - Desired security descriptor in SDDL format
Return Value: Win32 Error code
Written by: jobarner, 08/2002 --*/ DWORD SetDirSecurityFromReg(LPCTSTR lpszKey, LPCTSTR lpszVal, LPCTSTR lpszSD) { HKEY hKey = NULL; LPTSTR lpszFolder = NULL; DWORD ec = ERROR_SUCCESS;
DBG_ENTER(_T("SetDirSecurityFromReg"),ec);
hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, lpszKey, FALSE, KEY_READ); if (!hKey) { ec = GetLastError(); VERBOSE(SETUP_ERR, _T("OpenRegistryKey Failed, ec=%x"), ec); goto exit; }
lpszFolder = GetRegistryString(hKey, lpszVal, NULL); if (!lpszFolder) { ec = GetLastError(); VERBOSE(SETUP_ERR, _T("GetRegistryString Failed, ec=%x"), ec); goto exit; }
ec = SetDirSecurity(lpszFolder, lpszSD);
exit: if (lpszFolder) { MemFree(lpszFolder); } if (hKey) { RegCloseKey(hKey); } return ec; }
|