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.

579 lines
22 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. PCH_StartUp.CPP
  5. Abstract:
  6. WBEM provider class implementation for PCH_StartUp class
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 04/27/99
  9. - Created
  10. ********************************************************************/
  11. #include "pchealth.h"
  12. #include "PCH_StartUp.h"
  13. #include "shlobj.h"
  14. /////////////////////////////////////////////////////////////////////////////
  15. // tracing stuff
  16. #ifdef THIS_FILE
  17. #undef THIS_FILE
  18. #endif
  19. static char __szTraceSourceFile[] = __FILE__;
  20. #define THIS_FILE __szTraceSourceFile
  21. #define TRACE_ID DCID_STARTUP
  22. CPCH_StartUp MyPCH_StartUpSet (PROVIDER_NAME_PCH_STARTUP, PCH_NAMESPACE) ;
  23. // Property names
  24. //===============
  25. const static WCHAR* pTimeStamp = L"TimeStamp" ;
  26. const static WCHAR* pChange = L"Change" ;
  27. const static WCHAR* pCommand = L"Command" ;
  28. const static WCHAR* pLoadedFrom = L"LoadedFrom" ;
  29. const static WCHAR* pName = L"Name" ;
  30. //**************************************************************************************
  31. //
  32. // ResolveLink : Given the link file with complete Path, this function resolves it
  33. // to get its command line.
  34. //**************************************************************************************
  35. HRESULT ResolveLink(CComBSTR bstrLinkFile, // [in] link filename
  36. CComBSTR &bstrCommand // [out] cmd line of program
  37. // needs to be MAX_PATH*2 bytes long
  38. )
  39. {
  40. // Begin Declarations
  41. HRESULT hRes;
  42. IShellLink *pShellLink = NULL;
  43. IPersistFile *pPersistFile;
  44. TCHAR tchGotPath[MAX_PATH];
  45. TCHAR tchArgs[MAX_PATH];
  46. WIN32_FIND_DATA wfdFileData;
  47. // End Declarations
  48. // Get a pointer to the IShellLink interface.
  49. hRes = CoCreateInstance(CLSID_ShellLink, NULL,
  50. CLSCTX_INPROC_SERVER,
  51. IID_IShellLink,
  52. (LPVOID *) &pShellLink);
  53. if(SUCCEEDED(hRes))
  54. {
  55. // Get a pointer to the IPersistFile interface.
  56. hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
  57. if (SUCCEEDED(hRes))
  58. {
  59. // Load the shortcut.
  60. hRes = pPersistFile->Load(bstrLinkFile, STGM_READ);
  61. if(SUCCEEDED(hRes))
  62. {
  63. try
  64. {
  65. // Resolve the link.
  66. hRes = pShellLink->Resolve(NULL,
  67. SLR_NOTRACK|SLR_NOSEARCH|SLR_NO_UI|SLR_NOUPDATE);
  68. if (SUCCEEDED(hRes))
  69. {
  70. // Get the path to the link target.
  71. hRes = pShellLink->GetPath(tchGotPath,
  72. MAX_PATH,
  73. (WIN32_FIND_DATA *)&wfdFileData,
  74. SLGP_UNCPRIORITY );
  75. if(SUCCEEDED(hRes))
  76. {
  77. // bstrPath = tchGotPath;
  78. bstrCommand = tchGotPath;
  79. // Get cmd line arguments
  80. hRes = pShellLink->GetArguments(tchArgs, MAX_PATH);
  81. if(SUCCEEDED(hRes))
  82. {
  83. bstrCommand.Append(tchArgs);
  84. }
  85. }
  86. }
  87. }
  88. catch(...)
  89. {
  90. pPersistFile->Release();
  91. pShellLink->Release();
  92. throw;
  93. }
  94. }
  95. // Release the pointer to the IPersistFile interface.
  96. pPersistFile->Release();
  97. }
  98. // Release the pointer to the IShellLink interface.
  99. pShellLink->Release();
  100. }
  101. return hRes;
  102. }
  103. //**************************************************************************************
  104. //
  105. // UpdateInstance : Given all the properties for the instance this function copies
  106. // them to the instance.
  107. //
  108. //**************************************************************************************
  109. HRESULT UpdateInstance(
  110. CComVariant varName, // [in] Name of the Startup Instance
  111. CComVariant varLoadedFrom, // [in] Registry/StartupGroup
  112. CComVariant varCommand, // [in] Command of the startup Instance
  113. SYSTEMTIME stUTCTime, // [in]
  114. CInstancePtr pPCHStartupInstance, // [in/out] Instance is created by the caller.
  115. BOOL* fCommit
  116. )
  117. {
  118. TraceFunctEnter("::updateInstance");
  119. HRESULT hRes;
  120. CComVariant varSnapshot = "SnapShot";
  121. hRes = pPCHStartupInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime));
  122. if (FAILED(hRes))
  123. {
  124. // Could not Set the Time Stamp
  125. // Continue anyway
  126. ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
  127. }
  128. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. // CHANGE //
  130. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. hRes = pPCHStartupInstance->SetVariant(pChange, varSnapshot);
  132. if (FAILED(hRes))
  133. {
  134. // Could not Set the CHANGE property
  135. // Continue anyway
  136. ErrorTrace(TRACE_ID, "Set Variant on SnapShot Field failed.");
  137. }
  138. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. // NAME //
  140. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. hRes = pPCHStartupInstance->SetVariant(pName, varName);
  142. if (FAILED(hRes))
  143. {
  144. // Could not Set the NAME property
  145. // Continue anyway
  146. ErrorTrace(TRACE_ID, "SetVariant on Name Field failed.");
  147. }
  148. else
  149. {
  150. *fCommit = TRUE;
  151. }
  152. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. // LOADEDFROM //
  154. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  155. hRes = pPCHStartupInstance->SetVariant(pLoadedFrom, varLoadedFrom);
  156. if (FAILED(hRes))
  157. {
  158. // Could not Set the LOADEDFROM property
  159. // Continue anyway
  160. ErrorTrace(TRACE_ID, "Set variant on LOADEDFROM Field failed.");
  161. }
  162. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. // COMMAND //
  164. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  165. hRes = pPCHStartupInstance->SetVariant(pCommand, varCommand);
  166. if (FAILED(hRes))
  167. {
  168. // Could not Set the COMMAND property
  169. // Continue anyway
  170. ErrorTrace(TRACE_ID, "Set Variant on COMMAND Field failed.");
  171. }
  172. TraceFunctLeave();
  173. return(hRes);
  174. }
  175. //**************************************************************************************
  176. //
  177. // UpdateRegistryInstance : Given the Registry Root and the Hive this function creates
  178. // as many instances of PCH_StartUp Class as there are
  179. // entries in the particular hive.
  180. //
  181. //**************************************************************************************
  182. HRESULT CPCH_StartUp::UpdateRegistryInstance(
  183. HKEY hkeyRoot, // [in] For now this is either HKLM or HKCU
  184. LPCTSTR lpctstrRegistryHive, // [in] Registry hive to look for startup entries
  185. CComVariant varLoadedFrom, // [in] Constant string to fill the property "Loaded From"
  186. SYSTEMTIME stUTCTime, // [in] To fill up the "Timestamp" Field
  187. MethodContext* pMethodContext // [in] Required to create Instances.
  188. )
  189. {
  190. TraceFunctEnter("::UpdateRegistryInstance");
  191. // Begin Declarations
  192. HRESULT hRes;
  193. HKEY hkeyRun;
  194. DWORD dwIndex;
  195. DWORD dwType;
  196. DWORD dwNameSize;
  197. DWORD dwValueSize;
  198. TCHAR tchRunKeyName[MAX_PATH];
  199. TCHAR tchRunKeyValue[MAX_PATH];
  200. CComVariant varSnapshot = "SnapShot";
  201. CComVariant varCommand;
  202. CComVariant varName;
  203. LONG lregRetValue;
  204. BOOL fCommit = FALSE;
  205. // End Declarations
  206. // Initializations
  207. varCommand.Clear();
  208. varName.Clear();
  209. // Get the startup progrmas from the given registry Hive
  210. lregRetValue = RegOpenKeyEx(hkeyRoot, lpctstrRegistryHive, 0, KEY_QUERY_VALUE, &hkeyRun);
  211. if(lregRetValue == ERROR_SUCCESS)
  212. {
  213. // Opened the Registry key.
  214. // Enumerate the Name, Value pairs under this hive.
  215. // Initialize dwIndex, dwNameSize, dwValueSize
  216. dwIndex = 0;
  217. dwNameSize = MAX_PATH;
  218. dwValueSize = MAX_PATH;
  219. lregRetValue = RegEnumValue(hkeyRun, dwIndex, tchRunKeyName, &dwNameSize, NULL, NULL,(LPBYTE)tchRunKeyValue, &dwValueSize);
  220. while(lregRetValue == ERROR_SUCCESS)
  221. {
  222. // Got the Name and Value i.e "NAME" and "COMMAND"
  223. varName = tchRunKeyName;
  224. varCommand = tchRunKeyValue;
  225. // Create an instance of PCH_Startup
  226. // Create a new instance of PCH_StartupInstance Class based on the passed-in MethodContext
  227. CInstancePtr pPCHStartupInstance(CreateNewInstance(pMethodContext), false);
  228. // Call updateInstance now.
  229. try
  230. {
  231. hRes = UpdateInstance(varName, varLoadedFrom, varCommand, stUTCTime, pPCHStartupInstance, &fCommit);
  232. }
  233. catch(...)
  234. {
  235. lregRetValue = RegCloseKey(hkeyRun);
  236. if(lregRetValue != ERROR_SUCCESS)
  237. {
  238. // Could not Close the Key
  239. ErrorTrace(TRACE_ID, "Reg Close Key failed.");
  240. }
  241. throw;
  242. }
  243. if(fCommit)
  244. {
  245. hRes = pPCHStartupInstance->Commit();
  246. if(FAILED(hRes))
  247. {
  248. // Could not Commit the instance
  249. ErrorTrace(TRACE_ID, "Commit on PCHStartupInstance Failed");
  250. }
  251. }
  252. // Reinitialize dwNameSize and dwValueSize
  253. dwIndex++;
  254. dwNameSize = MAX_PATH;
  255. dwValueSize = MAX_PATH;
  256. lregRetValue = RegEnumValue(hkeyRun, dwIndex, tchRunKeyName, &dwNameSize, NULL, NULL,(LPBYTE)tchRunKeyValue, &dwValueSize);
  257. } // while Enum
  258. lregRetValue = RegCloseKey(hkeyRun);
  259. if(lregRetValue != ERROR_SUCCESS)
  260. {
  261. // Could not Close the Key
  262. ErrorTrace(TRACE_ID, "Reg Close Key failed.");
  263. }
  264. } // if SUCCEEDED
  265. TraceFunctLeave();
  266. return(hRes);
  267. }
  268. //**************************************************************************************
  269. //
  270. // UpdateStartupGroupInstance : Given the Startup Folder this function gets all the
  271. // link files in the folder and Calls the Function
  272. // ResolveLink to get the command Line of the Link File.
  273. // This also creates a PCH_Startup Class Instance for
  274. // each link file.
  275. //
  276. //**************************************************************************************
  277. HRESULT CPCH_StartUp::UpdateStartupGroupInstance(
  278. int nFolder, // [in] Special Folder to look for startup entries
  279. SYSTEMTIME stUTCTime, // [in]
  280. MethodContext* pMethodContext // [in] Instance is created by the caller.
  281. )
  282. {
  283. TraceFunctEnter("::UpdateStartupGroup Instance");
  284. // Begin Declarations
  285. HRESULT hRes;
  286. LPCTSTR lpctstrLinkExtension = _T("\\*.lnk");
  287. CComBSTR bstrPath;
  288. CComBSTR bstrSlash = "\\";
  289. CComBSTR bstrCommand;
  290. CComBSTR bstrPath1;
  291. TCHAR tchLinkFile[MAX_PATH];
  292. TCHAR tchProgramName[2*MAX_PATH];
  293. TCHAR tchPath[MAX_PATH];
  294. TCHAR tchFileName[MAX_PATH];
  295. LPCTSTR lpctstrCouldNot = "Could Not Resolve the File";
  296. CComVariant varCommand;
  297. CComVariant varName;
  298. CComVariant varLoadedFrom = "Startup Group";
  299. HANDLE hLinkFile;
  300. WIN32_FIND_DATA FindFileData;
  301. HWND hwndOwner = NULL;
  302. BOOL fCreate = FALSE;
  303. BOOL fShouldClose = FALSE;
  304. BOOL fContinue = FALSE;
  305. BOOL fCommit = FALSE;
  306. int nFileNameLen;
  307. int nExtLen = 4;
  308. // End Declarations
  309. // Get the Path to the passed in Special Folder nFolder
  310. if (SHGetSpecialFolderPath(hwndOwner,tchPath,nFolder,fCreate))
  311. {
  312. // Got the Startup Folder
  313. bstrPath1 = tchPath;
  314. bstrPath1.Append(bstrSlash);
  315. _tcscat(tchPath, lpctstrLinkExtension);
  316. hLinkFile = FindFirstFile(tchPath, &FindFileData); // data returned
  317. if(hLinkFile != INVALID_HANDLE_VALUE)
  318. {
  319. fContinue = TRUE;
  320. fShouldClose = TRUE;
  321. }
  322. else
  323. {
  324. fContinue = FALSE;
  325. fShouldClose = FALSE;
  326. }
  327. while(fContinue)
  328. {
  329. // Got the Link
  330. bstrPath = bstrPath1;
  331. bstrPath.Append(FindFileData.cFileName);
  332. // Take out the ".lnk" extension
  333. nFileNameLen = _tcslen(FindFileData.cFileName);
  334. nFileNameLen -= nExtLen;
  335. _tcsncpy(tchFileName, FindFileData.cFileName, nFileNameLen);
  336. tchFileName[nFileNameLen]='\0';
  337. varName = tchFileName;
  338. hRes = ResolveLink(bstrPath, bstrCommand);
  339. if(SUCCEEDED(hRes))
  340. {
  341. // Resolved the File Name
  342. varCommand = bstrCommand;
  343. }
  344. else
  345. {
  346. // Could not resolve the File
  347. varCommand = lpctstrCouldNot;
  348. }
  349. // Create an instance of PCH_Startup
  350. CInstancePtr pPCHStartupInstance(CreateNewInstance(pMethodContext), false);
  351. // Call updateInstance now.
  352. try
  353. {
  354. hRes = UpdateInstance(varName, varLoadedFrom, varCommand, stUTCTime, pPCHStartupInstance, &fCommit);
  355. }
  356. catch(...)
  357. {
  358. if (!FindClose(hLinkFile))
  359. {
  360. // Could not close the handle
  361. ErrorTrace(TRACE_ID, "Could not close the File Handle");
  362. }
  363. throw;
  364. }
  365. if(fCommit)
  366. {
  367. hRes = Commit(pPCHStartupInstance);
  368. if(FAILED(hRes))
  369. {
  370. // Could not Commit the instance
  371. ErrorTrace(TRACE_ID, "Commit on PCHStartupInstance Failed");
  372. }
  373. }
  374. if(!FindNextFile(hLinkFile, &FindFileData))
  375. {
  376. fContinue = FALSE;
  377. }
  378. }
  379. // Close the Find File Handle.
  380. if(fShouldClose)
  381. {
  382. if (!FindClose(hLinkFile))
  383. {
  384. // Could not close the handle
  385. ErrorTrace(TRACE_ID, "Could not close the File Handle");
  386. }
  387. }
  388. }
  389. return(hRes);
  390. TraceFunctLeave();
  391. }
  392. /*****************************************************************************
  393. *
  394. * FUNCTION : CPCH_StartUp::EnumerateInstances
  395. *
  396. * DESCRIPTION : Returns all the instances of this class.
  397. *
  398. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  399. * A long that contains the flags described in
  400. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  401. * flags are handled by (and filtered out by) WinMgmt:
  402. * WBEM_FLAG_DEEP
  403. * WBEM_FLAG_SHALLOW
  404. * WBEM_FLAG_RETURN_IMMEDIATELY
  405. * WBEM_FLAG_FORWARD_ONLY
  406. * WBEM_FLAG_BIDIRECTIONAL
  407. *
  408. * RETURNS : WBEM_S_NO_ERROR if successful
  409. *
  410. * COMMENTS : TO DO: All instances on the machine should be returned here.
  411. * If there are no instances, return WBEM_S_NO_ERROR.
  412. * It is not an error to have no instances.
  413. *
  414. *****************************************************************************/
  415. HRESULT CPCH_StartUp::EnumerateInstances(
  416. MethodContext* pMethodContext,
  417. long lFlags
  418. )
  419. {
  420. TraceFunctEnter("CPCH_StartUp::EnumerateInstances");
  421. // Begin Declarations...................................................
  422. HRESULT hRes = WBEM_S_NO_ERROR;
  423. SYSTEMTIME stUTCTime;
  424. // Registry Hives of interest
  425. LPCTSTR lpctstrRunHive = _T("software\\microsoft\\windows\\currentversion\\run");
  426. LPCTSTR lpctstrRunServicesHive = _T("software\\microsoft\\windows\\currentversion\\runservices");
  427. int nFolder;
  428. int nIndex;
  429. CComVariant varMachineRun = "Registry (Machine Run)";
  430. CComVariant varMachineService = "Registry (Machine Service)";
  431. CComVariant varPerUserRun = "Registry (Per User Run)";
  432. CComVariant varPerUserService = "Registry (Per User Service)";
  433. // End Declarations...................................................
  434. GetSystemTime(&stUTCTime);
  435. // Get the StartUp Programs From HKLM\software\microsoft\windows\currentversion\run
  436. hRes = UpdateRegistryInstance(HKEY_LOCAL_MACHINE, lpctstrRunHive, varMachineRun, stUTCTime, pMethodContext);
  437. if(hRes == WBEM_E_OUT_OF_MEMORY)
  438. {
  439. goto END;
  440. }
  441. // Get the StartUp Programs From HKLM\software\microsoft\windows\currentversion\runservices
  442. hRes = UpdateRegistryInstance(HKEY_LOCAL_MACHINE, lpctstrRunServicesHive, varMachineService, stUTCTime, pMethodContext);
  443. if(hRes == WBEM_E_OUT_OF_MEMORY)
  444. {
  445. goto END;
  446. }
  447. // Get the StartUp Programs From HKCU\software\microsoft\windows\currentversion\run
  448. hRes = UpdateRegistryInstance(HKEY_CURRENT_USER, lpctstrRunHive, varPerUserRun, stUTCTime, pMethodContext);
  449. if(hRes == WBEM_E_OUT_OF_MEMORY)
  450. {
  451. goto END;
  452. }
  453. // Get the StartUp Programs From HKCU\software\microsoft\windows\currentversion\runservices
  454. hRes = UpdateRegistryInstance(HKEY_CURRENT_USER, lpctstrRunServicesHive, varPerUserService, stUTCTime, pMethodContext);
  455. if(hRes == WBEM_E_OUT_OF_MEMORY)
  456. {
  457. goto END;
  458. }
  459. // Get the rest of the instances of startup programs from the Startup Group.
  460. // The two directories to look for are : Startup and common\startup
  461. // CSIDL_STARTUP (current user)
  462. hRes = UpdateStartupGroupInstance(CSIDL_STARTUP, stUTCTime, pMethodContext);
  463. if(hRes == WBEM_E_OUT_OF_MEMORY)
  464. {
  465. goto END;
  466. }
  467. // CSIDL_COMMON_STARTUP (all users)
  468. hRes = UpdateStartupGroupInstance(CSIDL_COMMON_STARTUP, stUTCTime, pMethodContext);
  469. END: TraceFunctLeave();
  470. return WBEM_S_NO_ERROR;
  471. }