Source code of Windows XP (NT5)
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.

410 lines
12 KiB

  1. /*++
  2. Copyright (C) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. PERSISTCFG.cpp
  5. Abstract:
  6. This file implements the WinMgmt persistent configuration operations.
  7. Classes implemented:
  8. CPersistentConfig persistent configuration manager
  9. History:
  10. 1/13/98 paulall Created.
  11. --*/
  12. #include "precomp.h"
  13. #include <memory.h>
  14. #include <stdio.h>
  15. #include "PersistCfg.h"
  16. #include "reg.h"
  17. #define WinMgmt_CFG_ACTUAL __TEXT("$WinMgmt.CFG")
  18. #define WinMgmt_CFG_PENDING __TEXT("$WinMgmt.$FG")
  19. #define WinMgmt_CFG_BACKUP __TEXT("$WinMgmt.CFG.BAK")
  20. CCritSec CPersistentConfig::m_cs;
  21. bool CPersistentConfig::m_bInitialized = false;
  22. CDirectoryPath CPersistentConfig::m_Directory;
  23. DWORD CPersistentConfig::m_ConfigValues[PERSIST_CFGVAL_MAX_NUM_EVENTS];
  24. /*=============================================================================
  25. * Constructor. Initialises the structure.
  26. *=============================================================================
  27. */
  28. CPersistentConfig::CPersistentConfig()
  29. {
  30. EnterCriticalSection(&m_cs);
  31. if((m_bInitialized == false) && (m_Directory.GetStr()))
  32. {
  33. memset(m_ConfigValues, 0, sizeof(DWORD) * MaxNumberConfigEntries);
  34. ReadConfig();
  35. m_bInitialized = true;
  36. }
  37. LeaveCriticalSection(&m_cs);
  38. }
  39. /*=============================================================================
  40. * GetPersistentCfgValue
  41. *
  42. * Retrieves the configuration from the configuration file if it
  43. * has not yet been retrieved into memory, or retrieves it from a
  44. * memory cache.
  45. *
  46. * Parameters:
  47. * dwOffset needs to be less than MaxNumberConfigEntries and specifies
  48. * the configuration entry required.
  49. * dwValue if sucessful this will contain the value. If the value
  50. * has not been set this will return 0.
  51. *
  52. * Return value:
  53. * BOOL returns TRUE if successful.
  54. *=============================================================================
  55. */
  56. BOOL CPersistentConfig::GetPersistentCfgValue(DWORD dwOffset, DWORD &dwValue)
  57. {
  58. if (dwOffset >= MaxNumberConfigEntries)
  59. return FALSE;
  60. EnterCriticalSection(&m_cs);
  61. dwValue = m_ConfigValues[dwOffset];
  62. LeaveCriticalSection(&m_cs);
  63. return TRUE;
  64. }
  65. /*=============================================================================
  66. * SetPersistentCfgValue
  67. *
  68. * Stores the value into the configuration file and to the
  69. * memory cache if it exists. The replacment of the original
  70. * file (if it exists) is the last thing it does.
  71. *
  72. * Parameters:
  73. * dwOffset needs to be less than MaxNumberConfigEntries and specifies
  74. * the configuration entry required.
  75. * dwValue is the value to set the configuration to.
  76. *
  77. * return value:
  78. * BOOL returns TRUE if successful.
  79. *=============================================================================
  80. */
  81. BOOL CPersistentConfig::SetPersistentCfgValue(DWORD dwOffset, DWORD dwValue)
  82. {
  83. if (dwOffset >= MaxNumberConfigEntries)
  84. return FALSE;
  85. EnterCriticalSection(&m_cs);
  86. //Do a check to make sure this is not what it is already set to. If it
  87. //is we do nothing. The write operation is slow! We do not want to do
  88. //unnecessary writes.
  89. DWORD dwCurValue;
  90. GetPersistentCfgValue(dwOffset, dwCurValue);
  91. if (dwValue == dwCurValue)
  92. {
  93. LeaveCriticalSection(&m_cs);
  94. return TRUE;
  95. }
  96. m_ConfigValues[dwOffset] = dwValue;
  97. BOOL bRet = WriteConfig();
  98. LeaveCriticalSection(&m_cs);
  99. return bRet;
  100. }
  101. /*=============================================================================
  102. * CDirectoryPath::CDirectoryPath
  103. *
  104. * Initialised the directory path
  105. *
  106. *=============================================================================
  107. */
  108. CDirectoryPath::CDirectoryPath()
  109. {
  110. Registry r(WBEM_REG_WINMGMT);
  111. Registry r1(WBEM_REG_WBEM);
  112. if (r.GetStr(__TEXT("Repository Directory"), &pszDirectory))
  113. {
  114. TCHAR *pszWorkDir = NULL;
  115. if (r1.GetStr(__TEXT("Installation Directory"), &pszWorkDir))
  116. {
  117. pszDirectory = NULL;
  118. return;
  119. }
  120. pszDirectory = new TCHAR [lstrlen(pszWorkDir) + lstrlen(__TEXT("\\Repository")) +1];
  121. if (pszDirectory)
  122. {
  123. wsprintf(pszDirectory, __TEXT("%s\\REPOSITORY"), pszWorkDir);
  124. r.SetStr(__TEXT("Repository Directory"), pszDirectory);
  125. }
  126. delete [] pszWorkDir;
  127. }
  128. }
  129. /*=============================================================================
  130. * ReadConfig
  131. *
  132. * Reads the $WinMgmt.CFG file into the memory cache
  133. *
  134. * return value:
  135. * BOOL returns TRUE if successful.
  136. *=============================================================================
  137. */
  138. BOOL CPersistentConfig::ReadConfig()
  139. {
  140. //Try and read the file if it exists, otherwise it does not matter, we just
  141. //return.
  142. TCHAR *pszFilename;
  143. pszFilename = GetFullFilename(WinMgmt_CFG_ACTUAL);
  144. HANDLE hFile = CreateFile(pszFilename, //Name of file
  145. GENERIC_READ, //Read only at
  146. 0, //Don't need to allow anyone else in
  147. 0, //Shouldn't need security
  148. OPEN_EXISTING, //Only open the file if it exists
  149. 0, //No attributes needed
  150. 0); //No template file required
  151. BOOL bRet = FALSE;
  152. if (hFile != INVALID_HANDLE_VALUE)
  153. {
  154. DWORD dwNumBytesRead;
  155. bRet =
  156. ReadFile(hFile,
  157. m_ConfigValues,
  158. sizeof(DWORD) * MaxNumberConfigEntries,
  159. &dwNumBytesRead,
  160. NULL);
  161. CloseHandle(hFile);
  162. }
  163. if (pszFilename)
  164. delete [] pszFilename;
  165. return bRet;
  166. }
  167. /*=============================================================================
  168. * WriteConfig
  169. *
  170. * Writes the $WinMgmt.CFG file into the memory cache and to the file. It
  171. * protects the existing file until the last minute.
  172. *
  173. * return value:
  174. * BOOL returns TRUE if successful.
  175. *=============================================================================
  176. */
  177. BOOL CPersistentConfig::WriteConfig()
  178. {
  179. TCHAR *pszActual = GetFullFilename(WinMgmt_CFG_ACTUAL);
  180. TCHAR *pszPending = GetFullFilename(WinMgmt_CFG_PENDING);
  181. TCHAR *pszBackup = GetFullFilename(WinMgmt_CFG_BACKUP);
  182. //Create a new file to write to...
  183. HANDLE hFile = CreateFile(pszPending, //Name of file
  184. GENERIC_WRITE, //Write only
  185. 0, //Don't need to allow anyone else in
  186. 0, //Shouldn't need security
  187. CREATE_ALWAYS, //Always create a new file
  188. 0, //No attributes needed
  189. 0); //No template file required
  190. if (hFile != INVALID_HANDLE_VALUE)
  191. {
  192. DWORD dwNumBytesWritten;
  193. if (!WriteFile(hFile,
  194. m_ConfigValues,
  195. sizeof(DWORD) * MaxNumberConfigEntries,
  196. &dwNumBytesWritten,
  197. NULL) ||
  198. (dwNumBytesWritten != (sizeof(DWORD) * MaxNumberConfigEntries)))
  199. {
  200. //OK, this failed!!!
  201. CloseHandle(hFile);
  202. //Delete the file...
  203. DeleteFile(pszPending);
  204. delete [] pszPending;
  205. delete [] pszActual;
  206. delete [] pszBackup;
  207. return FALSE;
  208. }
  209. //Make sure it really is flushed to the disk
  210. FlushFileBuffers(hFile);
  211. CloseHandle(hFile);
  212. //Rename the existing file
  213. DeleteFile(pszBackup);
  214. MoveFile(pszActual, pszBackup);
  215. //Move the new file here
  216. MoveFile(pszPending, pszActual);
  217. //Delete the old file
  218. DeleteFile(pszBackup);
  219. delete [] pszPending;
  220. delete [] pszActual;
  221. delete [] pszBackup;
  222. return TRUE;
  223. }
  224. delete [] pszPending;
  225. delete [] pszActual;
  226. delete [] pszBackup;
  227. return FALSE;
  228. }
  229. TCHAR *CPersistentConfig::GetFullFilename(const TCHAR *pszFilename)
  230. {
  231. TCHAR *pszPathFilename = new TCHAR[lstrlen(m_Directory.GetStr()) + lstrlen(pszFilename) + 2];
  232. if (pszPathFilename)
  233. {
  234. lstrcpy(pszPathFilename, m_Directory.GetStr());
  235. if ((lstrlen(pszPathFilename)) && (pszPathFilename[lstrlen(pszPathFilename)-1] != __TEXT('\\')))
  236. {
  237. lstrcat(pszPathFilename, __TEXT("\\"));
  238. }
  239. lstrcat(pszPathFilename, pszFilename);
  240. }
  241. return pszPathFilename;
  242. }
  243. void CPersistentConfig::TidyUp()
  244. {
  245. //Recover the configuration file.
  246. //-------------------------------
  247. TCHAR *pszOriginalFile = GetFullFilename(WinMgmt_CFG_ACTUAL);
  248. TCHAR *pszPendingFile = GetFullFilename(WinMgmt_CFG_PENDING);
  249. TCHAR *pszBackupFile = GetFullFilename(WinMgmt_CFG_BACKUP);
  250. if (FileExists(pszOriginalFile))
  251. {
  252. if (FileExists(pszPendingFile))
  253. {
  254. if (FileExists(pszBackupFile))
  255. {
  256. //BAD - Unexpected situation.
  257. DeleteFile(pszPendingFile);
  258. DeleteFile(pszBackupFile);
  259. //Back to the point where the interrupted operation did not
  260. //happen
  261. }
  262. else
  263. {
  264. //Pending file with original file means we cannot guarentee
  265. //the integrety of the pending file so the last operation
  266. //will be lost.
  267. DeleteFile(pszPendingFile);
  268. //Back to the point where the interrupted operation did not
  269. //happen
  270. }
  271. }
  272. else
  273. {
  274. if (FileExists(pszBackupFile))
  275. {
  276. //Means we successfully copied the pending file to the original
  277. DeleteFile(pszBackupFile);
  278. //Everything is now normal. Interrupted Operation completed!
  279. }
  280. else
  281. {
  282. //Nothing out of the ordinary here.
  283. }
  284. }
  285. }
  286. else
  287. {
  288. if (FileExists(pszPendingFile))
  289. {
  290. if (FileExists(pszBackupFile))
  291. {
  292. //This is an expected behaviour at the point we have renamed
  293. //the original file to the backup file.
  294. MoveFile(pszPendingFile, pszOriginalFile);
  295. DeleteFile(pszBackupFile);
  296. //Everything is now normal. Interrupted operation completed!
  297. }
  298. else
  299. {
  300. //BAD - Unexpected situation.
  301. DeleteFile(pszPendingFile);
  302. //There are now no files! Operation did not take place
  303. //and there are now no files left. This should be a
  304. //recoverable scenario!
  305. }
  306. }
  307. else
  308. {
  309. if (FileExists(pszBackupFile))
  310. {
  311. //BAD - Unexpected situation.
  312. DeleteFile(pszBackupFile);
  313. //There are now no files! Operation did not take place
  314. //and there are now no files left. This should be a
  315. //recoverable scenario!
  316. }
  317. else
  318. {
  319. //May be BAD! There are no files! This should be a
  320. //recoverable scenario!
  321. }
  322. }
  323. }
  324. delete [] pszOriginalFile;
  325. delete [] pszPendingFile;
  326. delete [] pszBackupFile;
  327. }
  328. //*****************************************************************************
  329. //
  330. // FileExists()
  331. //
  332. // Returns TRUE if the file exists, FALSE otherwise (or if an error
  333. // occurs while opening the file.
  334. //*****************************************************************************
  335. BOOL CPersistentConfig::FileExists(const TCHAR *pszFilename)
  336. {
  337. BOOL bExists = FALSE;
  338. HANDLE hFile = CreateFile(pszFilename, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  339. if (hFile != INVALID_HANDLE_VALUE)
  340. {
  341. bExists = TRUE;
  342. CloseHandle(hFile);
  343. }
  344. else
  345. {
  346. //If the file does not exist we should have a LastError of ERROR_NOT_FOUND
  347. DWORD dwError = GetLastError();
  348. if (dwError != ERROR_FILE_NOT_FOUND)
  349. {
  350. // DEBUGTRACE((LOG_WBEMCORE,"File %s could not be opened for a reason other than not existing\n", pszFilename));
  351. }
  352. }
  353. return bExists;
  354. }