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.

532 lines
17 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. winmgmt.cpp
  5. Abstract:
  6. HotMof directory functions
  7. --*/
  8. #include "precomp.h"
  9. #include <malloc.h>
  10. #include <mofcomp.h> // for AUTORECOVERY_REQUIRED
  11. #include "winmgmt.h" // this project
  12. #include "arrtempl.h" // for CDeleteMe
  13. //
  14. //
  15. // CheckNoResyncSwitch
  16. //
  17. //////////////////////////////////////////////////////////////////
  18. BOOL CheckNoResyncSwitch( void )
  19. {
  20. BOOL bRetVal = TRUE;
  21. DWORD dwVal = 0;
  22. Registry rCIMOM(WBEM_REG_WINMGMT);
  23. if (rCIMOM.GetDWORDStr( WBEM_NORESYNCPERF, &dwVal ) == Registry::no_error)
  24. {
  25. bRetVal = !dwVal;
  26. if ( bRetVal )
  27. {
  28. DEBUGTRACE((LOG_WINMGMT, "NoResyncPerf in CIMOM is set to TRUE - ADAP will not be shelled\n"));
  29. }
  30. }
  31. // If we didn't get anything there, we should try the volatile key
  32. if ( bRetVal )
  33. {
  34. Registry rAdap( HKEY_LOCAL_MACHINE, KEY_READ, WBEM_REG_ADAP);
  35. if ( rAdap.GetDWORD( WBEM_NOSHELL, &dwVal ) == Registry::no_error )
  36. {
  37. bRetVal = !dwVal;
  38. if ( bRetVal )
  39. {
  40. DEBUGTRACE((LOG_WINMGMT,
  41. "NoShell in ADAP is set to TRUE - ADAP will not be shelled\n"));
  42. }
  43. }
  44. }
  45. return bRetVal;
  46. }
  47. //
  48. //
  49. // CheckNoResyncSwitch
  50. //
  51. //////////////////////////////////////////////////////////////////
  52. BOOL
  53. CheckSetupSwitch( void )
  54. {
  55. BOOL bRetVal = FALSE;
  56. DWORD dwVal = 0;
  57. Registry r(WBEM_REG_WINMGMT);
  58. if (r.GetDWORDStr( WBEM_WMISETUP, &dwVal ) == Registry::no_error)
  59. {
  60. bRetVal = dwVal;
  61. DEBUGTRACE((LOG_WINMGMT, "Registry entry is indicating a setup is %d\n",bRetVal));
  62. }
  63. return bRetVal;
  64. }
  65. //
  66. //
  67. // CheckGlobalSetupSwitch
  68. //
  69. //////////////////////////////////////////////////////////////////
  70. BOOL
  71. CheckGlobalSetupSwitch( void )
  72. {
  73. BOOL bRetVal = FALSE;
  74. DWORD dwVal = 0;
  75. Registry r(TEXT("system\\Setup"));
  76. if (r.GetDWORD(TEXT("SystemSetupInProgress"), &dwVal ) == Registry::no_error)
  77. {
  78. if(dwVal == 1)
  79. bRetVal = TRUE;
  80. }
  81. return bRetVal;
  82. }
  83. //
  84. //
  85. //
  86. // This function will place a volatile registry key under the
  87. // CIMOM key in which we will write a value indicating
  88. // we should not shell ADAP. This way, after a setup runs, WINMGMT
  89. // will NOT automatically shell ADAP dredges of the registry,
  90. // until the system is rebooted and the volatile registry key is removed.
  91. //
  92. //
  93. ///////////////////////////////////////////////////////////////////////////
  94. void SetNoShellADAPSwitch( void )
  95. {
  96. DWORD dwDisposition = 0;
  97. Registry r( HKEY_LOCAL_MACHINE,
  98. REG_OPTION_VOLATILE, KEY_READ | KEY_WRITE, WBEM_REG_ADAP );
  99. if ( ERROR_SUCCESS == r.GetLastError() )
  100. {
  101. if ( r.SetDWORD( WBEM_NOSHELL, 1 ) != Registry::no_error )
  102. {
  103. DEBUGTRACE( ( LOG_WINMGMT, "Failed to create NoShell value in volatile reg key: %d\n",
  104. r.GetLastError() ) );
  105. }
  106. }
  107. else
  108. {
  109. DEBUGTRACE( ( LOG_WINMGMT, "Failed to create volatile ADAP reg key: %d\n", r.GetLastError() ) );
  110. }
  111. }
  112. //
  113. //
  114. // bool IsValidMulti
  115. //
  116. //
  117. // Does a sanity check on a multstring.
  118. //
  119. //////////////////////////////////////////////////////////////////////
  120. BOOL IsValidMulti(TCHAR * pMultStr, DWORD dwSize)
  121. {
  122. // Divide the size by the size of a tchar, in case these
  123. // are WCHAR strings
  124. dwSize /= sizeof(TCHAR);
  125. if(pMultStr && dwSize >= 2 && pMultStr[dwSize-2]==0 && pMultStr[dwSize-1]==0)
  126. return TRUE;
  127. return FALSE;
  128. }
  129. //
  130. //
  131. // BOOL IsStringPresetn
  132. //
  133. //
  134. // Searches a multstring for the presense of a string.
  135. //
  136. //
  137. ////////////////////////////////////////////////////////////////////
  138. BOOL IsStringPresent(TCHAR * pTest, TCHAR * pMultStr)
  139. {
  140. TCHAR * pTemp;
  141. for(pTemp = pMultStr; *pTemp; pTemp += lstrlen(pTemp) + 1)
  142. if(!lstrcmpi(pTest, pTemp))
  143. return TRUE;
  144. return FALSE;
  145. }
  146. //
  147. //
  148. // AddToAutoRecoverList
  149. //
  150. //
  151. ////////////////////////////////////////////////////////////////////
  152. void AddToAutoRecoverList(TCHAR * pFileName)
  153. {
  154. TCHAR cFullFileName[MAX_PATH+1];
  155. TCHAR * lpFile;
  156. DWORD dwSize;
  157. TCHAR * pNew = NULL;
  158. TCHAR * pTest;
  159. DWORD dwNewSize = 0;
  160. // Get the full file name
  161. long lRet = GetFullPathName(pFileName, MAX_PATH, cFullFileName, &lpFile);
  162. if(lRet == 0)
  163. return;
  164. BOOL bFound = FALSE;
  165. Registry r(WBEM_REG_WINMGMT);
  166. TCHAR *pMulti = r.GetMultiStr(__TEXT("Autorecover MOFs"), dwSize);
  167. CVectorDeleteMe<TCHAR> dm_(pMulti);
  168. // Ignore the empty string case
  169. if(dwSize == 1)
  170. {
  171. pMulti = NULL;
  172. }
  173. if(pMulti)
  174. {
  175. if(!IsValidMulti(pMulti, dwSize))
  176. {
  177. return; // bail out, messed up multistring
  178. }
  179. bFound = IsStringPresent(cFullFileName, pMulti);
  180. if(!bFound)
  181. {
  182. // The registry entry does exist, but doesnt have this name
  183. // Make a new multistring with the file name at the end
  184. dwNewSize = dwSize + ((lstrlen(cFullFileName) + 1) * sizeof(TCHAR));
  185. size_t cchSizeOld = dwSize / sizeof(TCHAR);
  186. size_t cchSizeNew = dwNewSize / sizeof(TCHAR);
  187. pNew = new TCHAR[cchSizeNew];
  188. if(!pNew) return;
  189. memcpy(pNew, pMulti, dwSize);
  190. // Find the double null
  191. for(pTest = pNew; pTest[0] || pTest[1]; pTest++); // intentional semi
  192. // Tack on the path and ensure a double null;
  193. pTest++;
  194. size_t cchSizeTmp = cchSizeNew - cchSizeOld;
  195. StringCchCopy(pTest,cchSizeTmp,cFullFileName);
  196. pTest+= lstrlen(cFullFileName)+1;
  197. *pTest = 0; // add second numm
  198. }
  199. }
  200. else
  201. {
  202. // The registry entry just doesnt exist.
  203. // Create it with a value equal to our name
  204. dwNewSize = ((lstrlen(cFullFileName) + 2) * sizeof(TCHAR));
  205. pNew = new TCHAR[dwNewSize / sizeof(TCHAR)];
  206. if(!pNew)
  207. return;
  208. size_t cchSizeTmp = dwNewSize / sizeof(TCHAR);
  209. StringCchCopy(pNew,cchSizeTmp, cFullFileName);
  210. pTest = pNew + lstrlen(pNew) + 1;
  211. *pTest = 0; // add second null
  212. }
  213. if(pNew)
  214. {
  215. // We will cast pNew, since the underlying function will have to cast to
  216. // LPBYTE and we will be WCHAR if UNICODE is defined
  217. r.SetMultiStr(__TEXT("Autorecover MOFs"), pNew, dwNewSize);
  218. delete [] pNew;
  219. }
  220. FILETIME ftCurTime;
  221. LARGE_INTEGER liCurTime;
  222. TCHAR szBuff[50];
  223. GetSystemTimeAsFileTime(&ftCurTime);
  224. liCurTime.LowPart = ftCurTime.dwLowDateTime;
  225. liCurTime.HighPart = ftCurTime.dwHighDateTime;
  226. _ui64tow(liCurTime.QuadPart, szBuff, 10);
  227. r.SetStr(__TEXT("Autorecover MOFs timestamp"), szBuff);
  228. }
  229. //
  230. // LoadMofsInDirectory
  231. //
  232. //
  233. ////////////////////////////////////////////////////////////////////////////////////////
  234. void LoadMofsInDirectory(const TCHAR *szDirectory)
  235. {
  236. if (NULL == szDirectory)
  237. return;
  238. if(CheckGlobalSetupSwitch())
  239. return; // not hot compiling during setup!
  240. size_t cchHotMof = lstrlen(szDirectory) + lstrlen(__TEXT("\\*")) + 1;
  241. TCHAR *szHotMofDirFF = new TCHAR[cchHotMof];
  242. if(!szHotMofDirFF)return;
  243. CDeleteMe<TCHAR> delMe1(szHotMofDirFF);
  244. size_t cchHotMofBad = lstrlen(szDirectory) + lstrlen(__TEXT("\\bad\\")) + 1;
  245. TCHAR *szHotMofDirBAD = new TCHAR[cchHotMofBad];
  246. if(!szHotMofDirBAD)return;
  247. CDeleteMe<TCHAR> delMe2(szHotMofDirBAD);
  248. size_t cchHotMofGood = lstrlen(szDirectory) + lstrlen(__TEXT("\\good\\")) + 1;
  249. TCHAR *szHotMofDirGOOD = new TCHAR[cchHotMofGood];
  250. if(!szHotMofDirGOOD)return;
  251. CDeleteMe<TCHAR> delMe3(szHotMofDirGOOD);
  252. IWinmgmtMofCompiler * pCompiler = NULL;
  253. //Find search parameter
  254. StringCchCopy(szHotMofDirFF,cchHotMof, szDirectory);
  255. StringCchCat(szHotMofDirFF,cchHotMof, __TEXT("\\*"));
  256. //Where bad mofs go
  257. StringCchCopy(szHotMofDirBAD,cchHotMofBad, szDirectory);
  258. StringCchCat(szHotMofDirBAD,cchHotMofBad, __TEXT("\\bad\\"));
  259. //Where good mofs go
  260. StringCchCopy(szHotMofDirGOOD,cchHotMofGood, szDirectory);
  261. StringCchCat(szHotMofDirGOOD,cchHotMofGood, __TEXT("\\good\\"));
  262. //Make sure directories exist
  263. WCHAR * pSDDL = TEXT("D:P(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)");
  264. if (FAILED(TestDirExistAndCreateWithSDIfNotThere((TCHAR *)szDirectory,pSDDL))) { return; };
  265. if (FAILED(TestDirExistAndCreateWithSDIfNotThere(szHotMofDirBAD,pSDDL))) { return; };
  266. if (FAILED(TestDirExistAndCreateWithSDIfNotThere(szHotMofDirGOOD,pSDDL))) { return; };
  267. //Find file...
  268. WIN32_FIND_DATA ffd;
  269. HANDLE hFF = FindFirstFile(szHotMofDirFF, &ffd);
  270. if (hFF != INVALID_HANDLE_VALUE)
  271. {
  272. OnDelete<HANDLE,BOOL(*)(HANDLE),FindClose> cm(hFF);
  273. do
  274. {
  275. //We only process if this is a file
  276. if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  277. {
  278. //Create a full filename with path
  279. size_t cchSizeTmp = lstrlen(szDirectory) + lstrlen(__TEXT("\\")) + lstrlen(ffd.cFileName) + 1;
  280. TCHAR *szFullFilename = new TCHAR[cchSizeTmp];
  281. if(!szFullFilename) return;
  282. CDeleteMe<TCHAR> delMe4(szFullFilename);
  283. StringCchCopy(szFullFilename,cchSizeTmp, szDirectory);
  284. StringCchCat(szFullFilename,cchSizeTmp, __TEXT("\\"));
  285. StringCchCat(szFullFilename,cchSizeTmp, ffd.cFileName);
  286. TRACE((LOG_WINMGMT,"Auto-loading MOF %s\n", szFullFilename));
  287. //We need to hold off on this file until it has been finished writing
  288. //otherwise the CompileFile will not be able to read the file!
  289. HANDLE hMof = INVALID_HANDLE_VALUE;
  290. DWORD dwRetry = 10;
  291. while (hMof == INVALID_HANDLE_VALUE)
  292. {
  293. hMof = CreateFile(szFullFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  294. //If cannot open yet sleep for a while
  295. if (hMof == INVALID_HANDLE_VALUE)
  296. {
  297. if (--dwRetry == 0)
  298. break;
  299. Sleep(1000);
  300. }
  301. }
  302. DWORD dwRetCode;
  303. WBEM_COMPILE_STATUS_INFO Info;
  304. DWORD dwAutoRecoverRequired = 0;
  305. if (hMof == INVALID_HANDLE_VALUE)
  306. {
  307. TRACE((LOG_WINMGMT,"Auto-loading MOF %s failed because we could not open it for exclusive access\n", szFullFilename));
  308. dwRetCode = 1;
  309. }
  310. else
  311. {
  312. CloseHandle(hMof);
  313. if (pCompiler == 0)
  314. {
  315. SCODE sc = CoCreateInstance(CLSID_MofCompilerOOP, 0,
  316. CLSCTX_LOCAL_SERVER| CLSCTX_ENABLE_AAA,
  317. IID_IWinmgmtMofCompilerOOP,
  318. (LPVOID *) &pCompiler);
  319. /*
  320. SCODE sc = CoCreateInstance(CLSID_WinmgmtMofCompiler,
  321. 0,
  322. CLSCTX_INPROC_SERVER,
  323. IID_IWinmgmtMofCompiler,
  324. (LPVOID *) &pCompiler);
  325. */
  326. if(sc != S_OK)
  327. return;
  328. }
  329. dwRetCode = pCompiler->WinmgmtCompileFile(szFullFilename,
  330. NULL,
  331. WBEM_FLAG_DONT_ADD_TO_LIST, // autocomp, check, etc
  332. 0,
  333. 0,
  334. NULL,
  335. NULL,
  336. &Info);
  337. }
  338. TCHAR *szNewDir = (dwRetCode?szHotMofDirBAD:szHotMofDirGOOD);
  339. cchSizeTmp = lstrlen(szNewDir) + lstrlen(ffd.cFileName) + 1;
  340. TCHAR *szNewFilename = new TCHAR[cchSizeTmp];
  341. if(!szNewFilename) return;
  342. CDeleteMe<TCHAR> delMe5(szNewFilename);
  343. StringCchCopy(szNewFilename,cchSizeTmp, szNewDir);
  344. StringCchCat(szNewFilename,cchSizeTmp, ffd.cFileName);
  345. //Make sure we have access to delete the old file...
  346. DWORD dwOldAttribs = GetFileAttributes(szNewFilename);
  347. if (dwOldAttribs != -1)
  348. {
  349. dwOldAttribs &= ~FILE_ATTRIBUTE_READONLY;
  350. SetFileAttributes(szNewFilename, dwOldAttribs);
  351. if (DeleteFile(szNewFilename))
  352. {
  353. TRACE((LOG_WINMGMT, "Removing old MOF %s\n", szNewFilename));
  354. }
  355. }
  356. TRACE((LOG_WINMGMT, "Loading of MOF %s was %s. Moving to %s\n", szFullFilename, dwRetCode?"unsuccessful":"successful", szNewFilename));
  357. MoveFile(szFullFilename, szNewFilename);
  358. //Now mark the file as read only so no one deletes it!!!
  359. //Like that stops anyone deleting files :-)
  360. dwOldAttribs = GetFileAttributes(szNewFilename);
  361. if (dwOldAttribs != -1)
  362. {
  363. dwOldAttribs |= FILE_ATTRIBUTE_READONLY;
  364. SetFileAttributes(szNewFilename, dwOldAttribs);
  365. }
  366. if ((dwRetCode == 0) && (Info.dwOutFlags & AUTORECOVERY_REQUIRED))
  367. {
  368. //We need to add this item into the registry for auto-recovery purposes
  369. TRACE((LOG_WINMGMT, "MOF %s had an auto-recover pragrma. Updating registry.\n", szNewFilename));
  370. AddToAutoRecoverList(szNewFilename);
  371. }
  372. }
  373. } while (FindNextFile(hFF, &ffd));
  374. }
  375. if (pCompiler)
  376. pCompiler->Release();
  377. }
  378. //
  379. //
  380. // bool InitHotMofStuff
  381. //
  382. //
  383. //////////////////////////////////////////////////////////////////
  384. BOOL InitHotMofStuff( IN OUT struct _PROG_RESOURCES * pProgRes)
  385. {
  386. // Get the installation directory
  387. if (pProgRes->szHotMofDirectory)
  388. {
  389. delete [] pProgRes->szHotMofDirectory;
  390. pProgRes->szHotMofDirectory = NULL;
  391. }
  392. Registry r1(WBEM_REG_WINMGMT);
  393. // The HotMof same permission as the autorecover
  394. TCHAR * pMofDir = NULL;
  395. if (r1.GetStr(__TEXT("MOF Self-Install Directory"), &pMofDir))
  396. {
  397. size_t cchSizeTmp = MAX_PATH + 1 + lstrlen(__TEXT("\\wbem\\mof"));
  398. pMofDir = new TCHAR[cchSizeTmp];
  399. if (NULL == pMofDir) return false;
  400. DWORD dwRet = GetSystemDirectory(pMofDir, MAX_PATH + 1);
  401. if (0 == dwRet || dwRet > (MAX_PATH)) { delete [] pMofDir; return false; }
  402. StringCchCat(pMofDir,cchSizeTmp, __TEXT("\\wbem\\mof"));
  403. if(r1.SetStr(__TEXT("MOF Self-Install Directory"),pMofDir) == Registry::failed)
  404. {
  405. ERRORTRACE((LOG_WINMGMT,"Unable to set 'Hot MOF Directory' in the registry\n"));
  406. delete [] pMofDir;
  407. return false;
  408. }
  409. }
  410. pProgRes->szHotMofDirectory = pMofDir;
  411. // Ensure the directory is there and secure it if not there
  412. // ===================================
  413. TCHAR * pString =TEXT("D:P(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)");
  414. HRESULT hRes;
  415. if (FAILED(hRes = TestDirExistAndCreateWithSDIfNotThere(pProgRes->szHotMofDirectory,pString)))
  416. {
  417. ERRORTRACE((LOG_WINMGMT,"TestDirExistAndCreateWithSDIfNotThere %S hr %08x\n",pMofDir,hRes));
  418. return false;
  419. }
  420. //Create an event on change notification for the MOF directory
  421. pProgRes->ghMofDirChange = FindFirstChangeNotification(pProgRes->szHotMofDirectory,
  422. FALSE,
  423. FILE_NOTIFY_CHANGE_FILE_NAME);
  424. if (pProgRes->ghMofDirChange == INVALID_HANDLE_VALUE)
  425. {
  426. pProgRes->ghMofDirChange = CreateEvent(NULL, FALSE, FALSE, NULL);
  427. if (pProgRes->ghMofDirChange == NULL)
  428. return false;
  429. }
  430. return true;
  431. }