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.
579 lines
22 KiB
579 lines
22 KiB
/********************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
PCH_StartUp.CPP
|
|
|
|
Abstract:
|
|
WBEM provider class implementation for PCH_StartUp class
|
|
|
|
Revision History:
|
|
|
|
Ghim-Sim Chua (gschua) 04/27/99
|
|
- Created
|
|
|
|
********************************************************************/
|
|
|
|
#include "pchealth.h"
|
|
#include "PCH_StartUp.h"
|
|
#include "shlobj.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// tracing stuff
|
|
|
|
#ifdef THIS_FILE
|
|
#undef THIS_FILE
|
|
#endif
|
|
static char __szTraceSourceFile[] = __FILE__;
|
|
#define THIS_FILE __szTraceSourceFile
|
|
#define TRACE_ID DCID_STARTUP
|
|
|
|
CPCH_StartUp MyPCH_StartUpSet (PROVIDER_NAME_PCH_STARTUP, PCH_NAMESPACE) ;
|
|
|
|
// Property names
|
|
//===============
|
|
const static WCHAR* pTimeStamp = L"TimeStamp" ;
|
|
const static WCHAR* pChange = L"Change" ;
|
|
const static WCHAR* pCommand = L"Command" ;
|
|
const static WCHAR* pLoadedFrom = L"LoadedFrom" ;
|
|
const static WCHAR* pName = L"Name" ;
|
|
|
|
|
|
//**************************************************************************************
|
|
//
|
|
// ResolveLink : Given the link file with complete Path, this function resolves it
|
|
// to get its command line.
|
|
//**************************************************************************************
|
|
|
|
HRESULT ResolveLink(CComBSTR bstrLinkFile, // [in] link filename
|
|
CComBSTR &bstrCommand // [out] cmd line of program
|
|
// needs to be MAX_PATH*2 bytes long
|
|
)
|
|
{
|
|
// Begin Declarations
|
|
|
|
HRESULT hRes;
|
|
IShellLink *pShellLink = NULL;
|
|
IPersistFile *pPersistFile;
|
|
TCHAR tchGotPath[MAX_PATH];
|
|
TCHAR tchArgs[MAX_PATH];
|
|
WIN32_FIND_DATA wfdFileData;
|
|
|
|
// End Declarations
|
|
|
|
// Get a pointer to the IShellLink interface.
|
|
hRes = CoCreateInstance(CLSID_ShellLink, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IShellLink,
|
|
(LPVOID *) &pShellLink);
|
|
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
// Get a pointer to the IPersistFile interface.
|
|
hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// Load the shortcut.
|
|
hRes = pPersistFile->Load(bstrLinkFile, STGM_READ);
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
try
|
|
{
|
|
// Resolve the link.
|
|
hRes = pShellLink->Resolve(NULL,
|
|
SLR_NOTRACK|SLR_NOSEARCH|SLR_NO_UI|SLR_NOUPDATE);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// Get the path to the link target.
|
|
hRes = pShellLink->GetPath(tchGotPath,
|
|
MAX_PATH,
|
|
(WIN32_FIND_DATA *)&wfdFileData,
|
|
SLGP_UNCPRIORITY );
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
// bstrPath = tchGotPath;
|
|
bstrCommand = tchGotPath;
|
|
// Get cmd line arguments
|
|
hRes = pShellLink->GetArguments(tchArgs, MAX_PATH);
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
bstrCommand.Append(tchArgs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
pPersistFile->Release();
|
|
pShellLink->Release();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Release the pointer to the IPersistFile interface.
|
|
pPersistFile->Release();
|
|
}
|
|
|
|
// Release the pointer to the IShellLink interface.
|
|
pShellLink->Release();
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
//**************************************************************************************
|
|
//
|
|
// UpdateInstance : Given all the properties for the instance this function copies
|
|
// them to the instance.
|
|
//
|
|
//**************************************************************************************
|
|
|
|
HRESULT UpdateInstance(
|
|
CComVariant varName, // [in] Name of the Startup Instance
|
|
CComVariant varLoadedFrom, // [in] Registry/StartupGroup
|
|
CComVariant varCommand, // [in] Command of the startup Instance
|
|
SYSTEMTIME stUTCTime, // [in]
|
|
CInstancePtr pPCHStartupInstance, // [in/out] Instance is created by the caller.
|
|
BOOL* fCommit
|
|
)
|
|
{
|
|
TraceFunctEnter("::updateInstance");
|
|
|
|
HRESULT hRes;
|
|
CComVariant varSnapshot = "SnapShot";
|
|
|
|
hRes = pPCHStartupInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime));
|
|
if (FAILED(hRes))
|
|
{
|
|
// Could not Set the Time Stamp
|
|
// Continue anyway
|
|
ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CHANGE //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
hRes = pPCHStartupInstance->SetVariant(pChange, varSnapshot);
|
|
if (FAILED(hRes))
|
|
{
|
|
// Could not Set the CHANGE property
|
|
// Continue anyway
|
|
ErrorTrace(TRACE_ID, "Set Variant on SnapShot Field failed.");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// NAME //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
hRes = pPCHStartupInstance->SetVariant(pName, varName);
|
|
if (FAILED(hRes))
|
|
{
|
|
// Could not Set the NAME property
|
|
// Continue anyway
|
|
ErrorTrace(TRACE_ID, "SetVariant on Name Field failed.");
|
|
}
|
|
else
|
|
{
|
|
*fCommit = TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// LOADEDFROM //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
hRes = pPCHStartupInstance->SetVariant(pLoadedFrom, varLoadedFrom);
|
|
if (FAILED(hRes))
|
|
{
|
|
// Could not Set the LOADEDFROM property
|
|
// Continue anyway
|
|
ErrorTrace(TRACE_ID, "Set variant on LOADEDFROM Field failed.");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// COMMAND //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
hRes = pPCHStartupInstance->SetVariant(pCommand, varCommand);
|
|
if (FAILED(hRes))
|
|
{
|
|
// Could not Set the COMMAND property
|
|
// Continue anyway
|
|
ErrorTrace(TRACE_ID, "Set Variant on COMMAND Field failed.");
|
|
}
|
|
|
|
|
|
TraceFunctLeave();
|
|
return(hRes);
|
|
|
|
}
|
|
|
|
//**************************************************************************************
|
|
//
|
|
// UpdateRegistryInstance : Given the Registry Root and the Hive this function creates
|
|
// as many instances of PCH_StartUp Class as there are
|
|
// entries in the particular hive.
|
|
//
|
|
//**************************************************************************************
|
|
|
|
HRESULT CPCH_StartUp::UpdateRegistryInstance(
|
|
HKEY hkeyRoot, // [in] For now this is either HKLM or HKCU
|
|
LPCTSTR lpctstrRegistryHive, // [in] Registry hive to look for startup entries
|
|
CComVariant varLoadedFrom, // [in] Constant string to fill the property "Loaded From"
|
|
SYSTEMTIME stUTCTime, // [in] To fill up the "Timestamp" Field
|
|
MethodContext* pMethodContext // [in] Required to create Instances.
|
|
)
|
|
{
|
|
TraceFunctEnter("::UpdateRegistryInstance");
|
|
|
|
// Begin Declarations
|
|
|
|
HRESULT hRes;
|
|
|
|
HKEY hkeyRun;
|
|
|
|
DWORD dwIndex;
|
|
DWORD dwType;
|
|
DWORD dwNameSize;
|
|
DWORD dwValueSize;
|
|
|
|
TCHAR tchRunKeyName[MAX_PATH];
|
|
TCHAR tchRunKeyValue[MAX_PATH];
|
|
|
|
|
|
CComVariant varSnapshot = "SnapShot";
|
|
CComVariant varCommand;
|
|
CComVariant varName;
|
|
|
|
LONG lregRetValue;
|
|
|
|
BOOL fCommit = FALSE;
|
|
|
|
|
|
|
|
// End Declarations
|
|
// Initializations
|
|
varCommand.Clear();
|
|
varName.Clear();
|
|
|
|
// Get the startup progrmas from the given registry Hive
|
|
|
|
lregRetValue = RegOpenKeyEx(hkeyRoot, lpctstrRegistryHive, 0, KEY_QUERY_VALUE, &hkeyRun);
|
|
if(lregRetValue == ERROR_SUCCESS)
|
|
{
|
|
// Opened the Registry key.
|
|
// Enumerate the Name, Value pairs under this hive.
|
|
// Initialize dwIndex, dwNameSize, dwValueSize
|
|
|
|
dwIndex = 0;
|
|
dwNameSize = MAX_PATH;
|
|
dwValueSize = MAX_PATH;
|
|
lregRetValue = RegEnumValue(hkeyRun, dwIndex, tchRunKeyName, &dwNameSize, NULL, NULL,(LPBYTE)tchRunKeyValue, &dwValueSize);
|
|
while(lregRetValue == ERROR_SUCCESS)
|
|
{
|
|
// Got the Name and Value i.e "NAME" and "COMMAND"
|
|
varName = tchRunKeyName;
|
|
varCommand = tchRunKeyValue;
|
|
|
|
// Create an instance of PCH_Startup
|
|
// Create a new instance of PCH_StartupInstance Class based on the passed-in MethodContext
|
|
CInstancePtr pPCHStartupInstance(CreateNewInstance(pMethodContext), false);
|
|
|
|
// Call updateInstance now.
|
|
try
|
|
{
|
|
hRes = UpdateInstance(varName, varLoadedFrom, varCommand, stUTCTime, pPCHStartupInstance, &fCommit);
|
|
}
|
|
catch(...)
|
|
{
|
|
lregRetValue = RegCloseKey(hkeyRun);
|
|
if(lregRetValue != ERROR_SUCCESS)
|
|
{
|
|
// Could not Close the Key
|
|
ErrorTrace(TRACE_ID, "Reg Close Key failed.");
|
|
}
|
|
throw;
|
|
}
|
|
if(fCommit)
|
|
{
|
|
hRes = pPCHStartupInstance->Commit();
|
|
if(FAILED(hRes))
|
|
{
|
|
// Could not Commit the instance
|
|
ErrorTrace(TRACE_ID, "Commit on PCHStartupInstance Failed");
|
|
}
|
|
}
|
|
|
|
// Reinitialize dwNameSize and dwValueSize
|
|
|
|
dwIndex++;
|
|
dwNameSize = MAX_PATH;
|
|
dwValueSize = MAX_PATH;
|
|
lregRetValue = RegEnumValue(hkeyRun, dwIndex, tchRunKeyName, &dwNameSize, NULL, NULL,(LPBYTE)tchRunKeyValue, &dwValueSize);
|
|
|
|
} // while Enum
|
|
lregRetValue = RegCloseKey(hkeyRun);
|
|
if(lregRetValue != ERROR_SUCCESS)
|
|
{
|
|
// Could not Close the Key
|
|
ErrorTrace(TRACE_ID, "Reg Close Key failed.");
|
|
}
|
|
} // if SUCCEEDED
|
|
|
|
TraceFunctLeave();
|
|
return(hRes);
|
|
|
|
}
|
|
//**************************************************************************************
|
|
//
|
|
// UpdateStartupGroupInstance : Given the Startup Folder this function gets all the
|
|
// link files in the folder and Calls the Function
|
|
// ResolveLink to get the command Line of the Link File.
|
|
// This also creates a PCH_Startup Class Instance for
|
|
// each link file.
|
|
//
|
|
//**************************************************************************************
|
|
|
|
HRESULT CPCH_StartUp::UpdateStartupGroupInstance(
|
|
int nFolder, // [in] Special Folder to look for startup entries
|
|
SYSTEMTIME stUTCTime, // [in]
|
|
MethodContext* pMethodContext // [in] Instance is created by the caller.
|
|
)
|
|
{
|
|
TraceFunctEnter("::UpdateStartupGroup Instance");
|
|
|
|
// Begin Declarations
|
|
|
|
HRESULT hRes;
|
|
|
|
LPCTSTR lpctstrLinkExtension = _T("\\*.lnk");
|
|
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrSlash = "\\";
|
|
CComBSTR bstrCommand;
|
|
CComBSTR bstrPath1;
|
|
|
|
TCHAR tchLinkFile[MAX_PATH];
|
|
TCHAR tchProgramName[2*MAX_PATH];
|
|
TCHAR tchPath[MAX_PATH];
|
|
TCHAR tchFileName[MAX_PATH];
|
|
LPCTSTR lpctstrCouldNot = "Could Not Resolve the File";
|
|
|
|
CComVariant varCommand;
|
|
CComVariant varName;
|
|
CComVariant varLoadedFrom = "Startup Group";
|
|
|
|
HANDLE hLinkFile;
|
|
|
|
WIN32_FIND_DATA FindFileData;
|
|
|
|
HWND hwndOwner = NULL;
|
|
|
|
BOOL fCreate = FALSE;
|
|
BOOL fShouldClose = FALSE;
|
|
BOOL fContinue = FALSE;
|
|
BOOL fCommit = FALSE;
|
|
|
|
int nFileNameLen;
|
|
int nExtLen = 4;
|
|
|
|
// End Declarations
|
|
|
|
|
|
|
|
// Get the Path to the passed in Special Folder nFolder
|
|
if (SHGetSpecialFolderPath(hwndOwner,tchPath,nFolder,fCreate))
|
|
{
|
|
// Got the Startup Folder
|
|
bstrPath1 = tchPath;
|
|
bstrPath1.Append(bstrSlash);
|
|
|
|
_tcscat(tchPath, lpctstrLinkExtension);
|
|
|
|
hLinkFile = FindFirstFile(tchPath, &FindFileData); // data returned
|
|
if(hLinkFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
fContinue = TRUE;
|
|
fShouldClose = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fContinue = FALSE;
|
|
fShouldClose = FALSE;
|
|
}
|
|
while(fContinue)
|
|
{
|
|
// Got the Link
|
|
bstrPath = bstrPath1;
|
|
bstrPath.Append(FindFileData.cFileName);
|
|
|
|
// Take out the ".lnk" extension
|
|
nFileNameLen = _tcslen(FindFileData.cFileName);
|
|
nFileNameLen -= nExtLen;
|
|
_tcsncpy(tchFileName, FindFileData.cFileName, nFileNameLen);
|
|
tchFileName[nFileNameLen]='\0';
|
|
varName = tchFileName;
|
|
hRes = ResolveLink(bstrPath, bstrCommand);
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
// Resolved the File Name
|
|
varCommand = bstrCommand;
|
|
}
|
|
else
|
|
{
|
|
// Could not resolve the File
|
|
varCommand = lpctstrCouldNot;
|
|
}
|
|
|
|
// Create an instance of PCH_Startup
|
|
CInstancePtr pPCHStartupInstance(CreateNewInstance(pMethodContext), false);
|
|
|
|
// Call updateInstance now.
|
|
try
|
|
{
|
|
hRes = UpdateInstance(varName, varLoadedFrom, varCommand, stUTCTime, pPCHStartupInstance, &fCommit);
|
|
}
|
|
catch(...)
|
|
{
|
|
if (!FindClose(hLinkFile))
|
|
{
|
|
// Could not close the handle
|
|
ErrorTrace(TRACE_ID, "Could not close the File Handle");
|
|
}
|
|
throw;
|
|
}
|
|
if(fCommit)
|
|
{
|
|
hRes = Commit(pPCHStartupInstance);
|
|
if(FAILED(hRes))
|
|
{
|
|
// Could not Commit the instance
|
|
ErrorTrace(TRACE_ID, "Commit on PCHStartupInstance Failed");
|
|
}
|
|
}
|
|
if(!FindNextFile(hLinkFile, &FindFileData))
|
|
{
|
|
fContinue = FALSE;
|
|
}
|
|
}
|
|
|
|
// Close the Find File Handle.
|
|
|
|
if(fShouldClose)
|
|
{
|
|
if (!FindClose(hLinkFile))
|
|
{
|
|
// Could not close the handle
|
|
ErrorTrace(TRACE_ID, "Could not close the File Handle");
|
|
}
|
|
}
|
|
|
|
}
|
|
return(hRes);
|
|
TraceFunctLeave();
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CPCH_StartUp::EnumerateInstances
|
|
*
|
|
* DESCRIPTION : Returns all the instances of this class.
|
|
*
|
|
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
|
|
* A long that contains the flags described in
|
|
* IWbemServices::CreateInstanceEnumAsync. Note that the following
|
|
* flags are handled by (and filtered out by) WinMgmt:
|
|
* WBEM_FLAG_DEEP
|
|
* WBEM_FLAG_SHALLOW
|
|
* WBEM_FLAG_RETURN_IMMEDIATELY
|
|
* WBEM_FLAG_FORWARD_ONLY
|
|
* WBEM_FLAG_BIDIRECTIONAL
|
|
*
|
|
* RETURNS : WBEM_S_NO_ERROR if successful
|
|
*
|
|
* COMMENTS : TO DO: All instances on the machine should be returned here.
|
|
* If there are no instances, return WBEM_S_NO_ERROR.
|
|
* It is not an error to have no instances.
|
|
*
|
|
*****************************************************************************/
|
|
HRESULT CPCH_StartUp::EnumerateInstances(
|
|
MethodContext* pMethodContext,
|
|
long lFlags
|
|
)
|
|
{
|
|
TraceFunctEnter("CPCH_StartUp::EnumerateInstances");
|
|
|
|
// Begin Declarations...................................................
|
|
|
|
HRESULT hRes = WBEM_S_NO_ERROR;
|
|
|
|
SYSTEMTIME stUTCTime;
|
|
|
|
// Registry Hives of interest
|
|
LPCTSTR lpctstrRunHive = _T("software\\microsoft\\windows\\currentversion\\run");
|
|
LPCTSTR lpctstrRunServicesHive = _T("software\\microsoft\\windows\\currentversion\\runservices");
|
|
|
|
int nFolder;
|
|
int nIndex;
|
|
|
|
CComVariant varMachineRun = "Registry (Machine Run)";
|
|
CComVariant varMachineService = "Registry (Machine Service)";
|
|
CComVariant varPerUserRun = "Registry (Per User Run)";
|
|
CComVariant varPerUserService = "Registry (Per User Service)";
|
|
|
|
|
|
// End Declarations...................................................
|
|
|
|
GetSystemTime(&stUTCTime);
|
|
|
|
// Get the StartUp Programs From HKLM\software\microsoft\windows\currentversion\run
|
|
hRes = UpdateRegistryInstance(HKEY_LOCAL_MACHINE, lpctstrRunHive, varMachineRun, stUTCTime, pMethodContext);
|
|
if(hRes == WBEM_E_OUT_OF_MEMORY)
|
|
{
|
|
goto END;
|
|
}
|
|
|
|
// Get the StartUp Programs From HKLM\software\microsoft\windows\currentversion\runservices
|
|
hRes = UpdateRegistryInstance(HKEY_LOCAL_MACHINE, lpctstrRunServicesHive, varMachineService, stUTCTime, pMethodContext);
|
|
if(hRes == WBEM_E_OUT_OF_MEMORY)
|
|
{
|
|
goto END;
|
|
}
|
|
|
|
|
|
// Get the StartUp Programs From HKCU\software\microsoft\windows\currentversion\run
|
|
hRes = UpdateRegistryInstance(HKEY_CURRENT_USER, lpctstrRunHive, varPerUserRun, stUTCTime, pMethodContext);
|
|
if(hRes == WBEM_E_OUT_OF_MEMORY)
|
|
{
|
|
goto END;
|
|
}
|
|
|
|
|
|
// Get the StartUp Programs From HKCU\software\microsoft\windows\currentversion\runservices
|
|
hRes = UpdateRegistryInstance(HKEY_CURRENT_USER, lpctstrRunServicesHive, varPerUserService, stUTCTime, pMethodContext);
|
|
if(hRes == WBEM_E_OUT_OF_MEMORY)
|
|
{
|
|
goto END;
|
|
}
|
|
|
|
|
|
// Get the rest of the instances of startup programs from the Startup Group.
|
|
// The two directories to look for are : Startup and common\startup
|
|
|
|
// CSIDL_STARTUP (current user)
|
|
hRes = UpdateStartupGroupInstance(CSIDL_STARTUP, stUTCTime, pMethodContext);
|
|
if(hRes == WBEM_E_OUT_OF_MEMORY)
|
|
{
|
|
goto END;
|
|
}
|
|
|
|
// CSIDL_COMMON_STARTUP (all users)
|
|
hRes = UpdateStartupGroupInstance(CSIDL_COMMON_STARTUP, stUTCTime, pMethodContext);
|
|
|
|
END: TraceFunctLeave();
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
}
|