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.

585 lines
15 KiB

  1. // template.cpp: implementation of the CSecurityTemplate class.
  2. // template.cpp
  3. // Copyright (c)1999-2001 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "Template.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. LPCWSTR pszRelSecTemplateDir = L"\\security\\templates\\";
  12. LPCWSTR pszSecTemplateFileExt = L"*.inf";
  13. LPCWSTR pszDescription = L"Description";
  14. LPCWSTR pszVersion = L"Version";
  15. LPCWSTR pszRevision = L"Revision";
  16. /*
  17. Routine Description:
  18. Name:
  19. CSecurityTemplate::CSecurityTemplate
  20. Functionality:
  21. This is the constructor. Pass along the parameters to the base class
  22. Virtual:
  23. No (you know that, constructor won't be virtual!)
  24. Arguments:
  25. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  26. by the caller who constructs this instance.
  27. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  28. Passed along by the caller. Must not be NULL.
  29. pCtx - Pointer to WMI context object (COM interface). Passed along
  30. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  31. Return Value:
  32. None as any constructor
  33. Notes:
  34. if you create any local members, think about initialize them here
  35. */
  36. CSecurityTemplate::CSecurityTemplate (
  37. IN ISceKeyChain * pKeyChain,
  38. IN IWbemServices * pNamespace,
  39. IN IWbemContext * pCtx
  40. )
  41. :
  42. CGenericClass(pKeyChain, pNamespace, pCtx)
  43. {
  44. }
  45. /*
  46. Routine Description:
  47. Name:
  48. CSecurityTemplate::~CSecurityTemplate
  49. Functionality:
  50. Destructor. Necessary as good C++ discipline since we have virtual functions.
  51. Virtual:
  52. Yes.
  53. Arguments:
  54. none as any destructor
  55. Return Value:
  56. None as any destructor
  57. Notes:
  58. if you create any local members, think about whether
  59. there is any need for a non-trivial destructor
  60. */
  61. CSecurityTemplate::~CSecurityTemplate()
  62. {
  63. }
  64. /*
  65. Routine Description:
  66. Name:
  67. CSecurityTemplate::CreateObject
  68. Functionality:
  69. Create WMI objects (Sce_Template). Depending on parameter atAction,
  70. this creation may mean:
  71. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  72. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  73. (c) Enumerate instances (atAction == ACTIONTYPE_ENUM)
  74. Virtual:
  75. Yes.
  76. Arguments:
  77. pHandler - COM interface pointer for notifying WMI for creation result.
  78. atAction - Get single instance ACTIONTYPE_GET
  79. Get several instances ACTIONTYPE_QUERY
  80. Enumerate instances ACTIONTYPE_ENUM
  81. Return Value:
  82. Success: it must return success code (use SUCCEEDED to test). It is
  83. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  84. not directly passed back via parameters.
  85. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  86. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  87. situations, this may not be an error depending on caller's intention.
  88. Notes:
  89. */
  90. HRESULT
  91. CSecurityTemplate::CreateObject (
  92. IN IWbemObjectSink * pHandler,
  93. IN ACTIONTYPE atAction
  94. )
  95. {
  96. //
  97. // we know how to:
  98. // Enumerate instances ACTIONTYPE_ENUM
  99. // Get single instance ACTIONTYPE_GET
  100. // Get several instances ACTIONTYPE_QUERY
  101. //
  102. if ( ACTIONTYPE_ENUM != atAction &&
  103. ACTIONTYPE_GET != atAction &&
  104. ACTIONTYPE_QUERY != atAction )
  105. {
  106. return WBEM_E_NOT_SUPPORTED;
  107. }
  108. DWORD dwCount = 0;
  109. HRESULT hr = m_srpKeyChain->GetKeyPropertyCount(&dwCount);
  110. if (FAILED(hr))
  111. {
  112. return hr;
  113. }
  114. if ( ACTIONTYPE_ENUM == atAction ||
  115. (ACTIONTYPE_QUERY == atAction && dwCount == 0) ) {
  116. //
  117. // enumeration of all templates in the path
  118. // if path is not defined, enumerate existing templates
  119. // in %windir%\security\templates directory
  120. //
  121. //
  122. // Prepare %windir% directory
  123. //
  124. //
  125. // system windows directory is < MAX_PATH, the security template dir is < MAX_PATH
  126. //
  127. WCHAR szTemplateDir[MAX_PATH * 2 + 1];
  128. szTemplateDir[0] = L'\0';
  129. //
  130. // szTemplateDir is merely the system windows directory
  131. //
  132. UINT uDirLen = ::GetSystemWindowsDirectory(szTemplateDir, MAX_PATH);
  133. szTemplateDir[MAX_PATH - 1] = L'\0';
  134. //
  135. // szTemplateDir will now be the real security template dir
  136. //
  137. wcscat(szTemplateDir, pszRelSecTemplateDir);
  138. //
  139. // security template dir's length
  140. //
  141. uDirLen += wcslen(pszRelSecTemplateDir);
  142. //
  143. // security template dir is < 2 * MAX_PATH, plus the file
  144. //
  145. WCHAR szFile[3 * MAX_PATH + 1];
  146. wcscpy(szFile, szTemplateDir);
  147. //
  148. // szFile is the search file filter
  149. //
  150. wcscat(szFile, pszSecTemplateFileExt);
  151. //
  152. // Enumerate all templates in %windir%\security\templates directory
  153. //
  154. struct _wfinddata_t FileInfo;
  155. intptr_t hFile = _wfindfirst(szFile, &FileInfo);
  156. if ( hFile != -1 )
  157. {
  158. //
  159. // find some files
  160. //
  161. do
  162. {
  163. //
  164. // remember: szFile + uDirLen is where the file name starts
  165. //
  166. wcscpy((LPWSTR)(szFile + uDirLen), FileInfo.name);
  167. //
  168. // got the template file name, we can constrcut the instance now.
  169. //
  170. hr = ConstructInstance(pHandler, szFile, szFile, (FileInfo.attrib & _A_RDONLY));
  171. } while ( SUCCEEDED(hr) && _wfindnext(hFile, &FileInfo) == 0 );
  172. _findclose(hFile);
  173. }
  174. }
  175. else if (dwCount == 1)
  176. {
  177. hr = WBEM_E_INVALID_OBJECT_PATH;
  178. //
  179. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  180. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  181. //
  182. CComVariant var;
  183. hr = m_srpKeyChain->GetKeyPropertyValue(pPath, &var);
  184. if (SUCCEEDED(hr) && hr != WBEM_S_FALSE && var.vt == VT_BSTR)
  185. {
  186. //
  187. // Create the template instance
  188. //
  189. CComBSTR bstrPath;
  190. BOOL bDb = FALSE;
  191. hr = CheckAndExpandPath(var.bstrVal, &bstrPath, &bDb);
  192. if ( bDb )
  193. {
  194. hr = WBEM_E_INVALID_OBJECT_PATH;
  195. }
  196. else if ( SUCCEEDED(hr) && (LPCWSTR)bstrPath != NULL )
  197. {
  198. //
  199. // make sure the store (just a file) really exists.
  200. //
  201. DWORD dwAttrib = GetFileAttributes(bstrPath);
  202. if ( dwAttrib != -1 )
  203. {
  204. //
  205. // got the template file name, we can constrcut the instance now.
  206. //
  207. hr = ConstructInstance(pHandler, bstrPath, var.bstrVal, (dwAttrib & FILE_ATTRIBUTE_READONLY));
  208. }
  209. else
  210. {
  211. hr = WBEM_E_NOT_FOUND;
  212. }
  213. }
  214. }
  215. }
  216. return hr;
  217. }
  218. /*
  219. Routine Description:
  220. Name:
  221. CSecurityTemplate::PutInst
  222. Functionality:
  223. Put an instance as instructed by WMI. Since this class implements Sce_Template,
  224. which is persistence oriented, this will cause the Sce_Template object's property
  225. information to be saved in our store.
  226. Virtual:
  227. Yes.
  228. Arguments:
  229. pInst - COM interface pointer to the WMI class (Sce_Template) object.
  230. pHandler - COM interface pointer for notifying WMI of any events.
  231. pCtx - COM interface pointer. This interface is just something we pass around.
  232. WMI may mandate it (not now) in the future. But we never construct
  233. such an interface and so, we just pass around for various WMI API's
  234. Return Value:
  235. Success: it must return success code (use SUCCEEDED to test). It is
  236. not guaranteed to return WBEM_NO_ERROR.
  237. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  238. the instance.
  239. Notes:
  240. (1) Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  241. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  242. to test for the result of retrieving a property.
  243. (2) For this class, only Description is writable
  244. */
  245. HRESULT
  246. CSecurityTemplate::PutInst (
  247. IN IWbemClassObject * pInst,
  248. IN IWbemObjectSink * pHandler,
  249. IN IWbemContext * pCtx
  250. )
  251. {
  252. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  253. //
  254. // CScePropertyMgr helps us to access WMI object's properties
  255. // create an instance and attach the WMI object to it.
  256. // This will always succeed.
  257. //
  258. CScePropertyMgr ScePropMgr;
  259. ScePropMgr.Attach(pInst);
  260. CComBSTR bstrDescription;
  261. hr = ScePropMgr.GetProperty(pDescription, &bstrDescription);
  262. if (SUCCEEDED(hr))
  263. {
  264. //
  265. // Attach the WMI object instance to the store and let the store know that
  266. // it's store is given by the pStorePath property of the instance.
  267. //
  268. CSceStore SceStore;
  269. hr = SceStore.SetPersistProperties(pInst, pPath);
  270. //
  271. // now save the info to file
  272. //
  273. if (SUCCEEDED(hr))
  274. {
  275. //
  276. // make sure the store (just a file) really exists. The raw path
  277. // may contain env variables, so we need the expanded path
  278. //
  279. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  280. if ( dwAttrib == -1 )
  281. {
  282. DWORD dwDump;
  283. //
  284. // For a new .inf file. Write an empty buffer to the file
  285. // will creates the file with right header/signature/unicode format
  286. // this is harmless for existing files.
  287. // For database store, this is a no-op.
  288. //
  289. hr = SceStore.WriteSecurityProfileInfo(AreaBogus, (PSCE_PROFILE_INFO)&dwDump, NULL, false);
  290. }
  291. if (SUCCEEDED(hr))
  292. {
  293. //
  294. // remove the entire description section
  295. //
  296. hr = SceStore.SavePropertyToStore(szDescription, NULL, (LPCWSTR)NULL);
  297. }
  298. if (SUCCEEDED(hr))
  299. {
  300. //
  301. // write the new description
  302. //
  303. hr = SceStore.SavePropertyToStore(szDescription, pszDescription, bstrDescription);
  304. }
  305. }
  306. }
  307. return hr;
  308. }
  309. /*
  310. Routine Description:
  311. Name:
  312. CSecurityTemplate::ConstructInstance
  313. Functionality:
  314. This is private function to create an instance of Sce_Template.
  315. Virtual:
  316. No.
  317. Arguments:
  318. pHandler - COM interface pointer for notifying WMI of any events.
  319. wszTemplateName - Name of the template.
  320. wszLogStorePath - store path, a key property of Sce_Template class.
  321. bReadOnly - a property of Sce_Template class
  322. Return Value:
  323. Success: it must return success code (use SUCCEEDED to test). It is
  324. not guaranteed to return WBEM_NO_ERROR.
  325. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  326. Notes:
  327. */
  328. HRESULT
  329. CSecurityTemplate::ConstructInstance (
  330. IN IWbemObjectSink * pHandler,
  331. IN LPCWSTR wszTemplateName,
  332. IN LPCWSTR wszLogStorePath,
  333. IN BOOL bReadOnly
  334. )
  335. {
  336. //
  337. // Get description from the INF template
  338. //
  339. HRESULT hr = WBEM_S_NO_ERROR;
  340. SCESTATUS rc;
  341. PVOID hProfile = NULL;
  342. DWORD dwRevision = 0;
  343. rc = SceOpenProfile(wszTemplateName, SCE_INF_FORMAT, &hProfile);
  344. if ( rc != SCESTATUS_SUCCESS )
  345. {
  346. //
  347. // SCE returned errors needs to be translated to HRESULT.
  348. //
  349. return ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  350. }
  351. LPWSTR wszDescription=NULL;
  352. CComBSTR bstrLogOut;
  353. CComPtr<IWbemClassObject> srpObj;
  354. //
  355. // CScePropertyMgr helps us to access WMI object's properties.
  356. //
  357. CScePropertyMgr ScePropMgr;
  358. //
  359. // description is not required so it could be NULL
  360. //
  361. //
  362. // need to free wszDescription
  363. //
  364. rc = SceGetScpProfileDescription( hProfile, &wszDescription );
  365. //
  366. // reading is over, so close the profile
  367. //
  368. SceCloseProfile( &hProfile );
  369. hProfile = NULL;
  370. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND )
  371. {
  372. //
  373. // SCE returned errors needs to be translated to HRESULT.
  374. //
  375. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  376. goto CleanUp;
  377. }
  378. //
  379. // Get version from the INF template
  380. //
  381. dwRevision = GetPrivateProfileInt(pszVersion, pszRevision, 0, wszTemplateName);
  382. //
  383. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  384. // a "goto CleanUp;" with hr set to the return value from
  385. // the function (macro parameter)
  386. //
  387. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut));
  388. SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj));
  389. //
  390. // attach a WMI object to the property mgr.
  391. // This will always succeed.
  392. //
  393. ScePropMgr.Attach(srpObj);
  394. //
  395. // put path and descriptions
  396. //
  397. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pPath, bstrLogOut));
  398. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDescription, wszDescription));
  399. //
  400. // put Revision
  401. //
  402. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pVersion, dwRevision));
  403. //
  404. // put bReadOnly and dirty
  405. //
  406. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pReadonly, bReadOnly ? true : false));
  407. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDirty, false));
  408. SCE_PROV_IfErrorGotoCleanup(pHandler->Indicate(1, &srpObj));
  409. CleanUp:
  410. delete [] wszDescription;
  411. return hr;
  412. }