|
|
/********************************************************************
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;
}
|