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.

481 lines
13 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. iml.c
  5. Abstract:
  6. This module contains routines for creating and accessing Installation
  7. Modification Log files (.IML)
  8. Author:
  9. Steve Wood (stevewo) 15-Jan-1996
  10. Revision History:
  11. --*/
  12. #include "instutil.h"
  13. #include "iml.h"
  14. PWSTR
  15. FormatImlPath(
  16. PWSTR DirectoryPath,
  17. PWSTR InstallationName
  18. )
  19. {
  20. PWSTR ImlPath;
  21. ULONG n;
  22. n = wcslen( DirectoryPath ) + wcslen( InstallationName ) + 8;
  23. ImlPath = HeapAlloc( GetProcessHeap(), 0, (n * sizeof( WCHAR )) );
  24. if (ImlPath != NULL) {
  25. _snwprintf( ImlPath, n, L"%s%s.IML", DirectoryPath, InstallationName );
  26. }
  27. return ImlPath;
  28. }
  29. PINSTALLATION_MODIFICATION_LOGFILE
  30. CreateIml(
  31. PWSTR ImlPath,
  32. BOOLEAN IncludeCreateFileContents
  33. )
  34. {
  35. HANDLE FileHandle;
  36. PINSTALLATION_MODIFICATION_LOGFILE pIml;
  37. pIml = NULL;
  38. FileHandle = CreateFile( ImlPath,
  39. GENERIC_READ | GENERIC_WRITE,
  40. FILE_SHARE_READ,
  41. NULL,
  42. OPEN_ALWAYS,
  43. 0,
  44. NULL
  45. );
  46. if (FileHandle != INVALID_HANDLE_VALUE) {
  47. pIml = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *pIml ) );
  48. if (pIml != NULL) {
  49. pIml->Signature = IML_SIGNATURE;
  50. pIml->FileHandle = FileHandle;
  51. pIml->FileOffset = ROUND_UP( sizeof( *pIml ), 8 );
  52. if (IncludeCreateFileContents) {
  53. pIml->Flags = IML_FLAG_CONTAINS_NEWFILECONTENTS;
  54. }
  55. SetFilePointer( pIml->FileHandle, pIml->FileOffset, NULL, FILE_BEGIN );
  56. }
  57. }
  58. return pIml;
  59. }
  60. PINSTALLATION_MODIFICATION_LOGFILE
  61. LoadIml(
  62. PWSTR ImlPath
  63. )
  64. {
  65. HANDLE FileHandle, MappingHandle;
  66. PINSTALLATION_MODIFICATION_LOGFILE pIml;
  67. pIml = NULL;
  68. FileHandle = CreateFile( ImlPath,
  69. GENERIC_READ,
  70. FILE_SHARE_READ,
  71. NULL,
  72. OPEN_EXISTING,
  73. 0,
  74. NULL
  75. );
  76. if (FileHandle != INVALID_HANDLE_VALUE) {
  77. MappingHandle = CreateFileMapping( FileHandle,
  78. NULL,
  79. PAGE_READONLY,
  80. 0,
  81. 0,
  82. NULL
  83. );
  84. CloseHandle( FileHandle );
  85. if (MappingHandle != NULL) {
  86. pIml = MapViewOfFile( MappingHandle,
  87. FILE_MAP_READ,
  88. 0,
  89. 0,
  90. 0
  91. );
  92. CloseHandle( MappingHandle );
  93. if (pIml != NULL) {
  94. if (pIml->Signature != IML_SIGNATURE) {
  95. UnmapViewOfFile( pIml );
  96. pIml = NULL;
  97. SetLastError( ERROR_BAD_FORMAT );
  98. }
  99. }
  100. }
  101. }
  102. return pIml;
  103. }
  104. BOOLEAN
  105. CloseIml(
  106. PINSTALLATION_MODIFICATION_LOGFILE pIml
  107. )
  108. {
  109. HANDLE FileHandle;
  110. BOOLEAN Result;
  111. ULONG BytesWritten;
  112. if (pIml->FileHandle == NULL) {
  113. if (!UnmapViewOfFile( pIml )) {
  114. return FALSE;
  115. }
  116. else {
  117. Result = TRUE;
  118. }
  119. }
  120. else {
  121. FileHandle = pIml->FileHandle;
  122. pIml->FileHandle = NULL;
  123. if (!SetEndOfFile( FileHandle ) ||
  124. SetFilePointer( FileHandle, 0, NULL, FILE_BEGIN ) != 0 ||
  125. !WriteFile( FileHandle,
  126. pIml,
  127. sizeof( *pIml ),
  128. &BytesWritten,
  129. NULL
  130. ) ||
  131. BytesWritten != sizeof( *pIml )
  132. ) {
  133. Result = FALSE;
  134. }
  135. else {
  136. Result = TRUE;
  137. }
  138. CloseHandle( FileHandle );
  139. }
  140. return Result;
  141. }
  142. POFFSET
  143. ImlWrite(
  144. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  145. PVOID p,
  146. ULONG Size
  147. )
  148. {
  149. POFFSET Result;
  150. ULONG BytesWritten;
  151. if (!WriteFile( pIml->FileHandle,
  152. p,
  153. Size,
  154. &BytesWritten,
  155. NULL
  156. ) ||
  157. BytesWritten != Size
  158. ) {
  159. return 0;
  160. }
  161. Result = pIml->FileOffset;
  162. pIml->FileOffset += ROUND_UP( Size, 8 );
  163. SetFilePointer( pIml->FileHandle,
  164. pIml->FileOffset,
  165. NULL,
  166. FILE_BEGIN
  167. );
  168. return Result;
  169. }
  170. POFFSET
  171. ImlWriteString(
  172. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  173. PWSTR Name
  174. )
  175. {
  176. if (Name == NULL) {
  177. return 0;
  178. }
  179. else {
  180. return ImlWrite( pIml, Name, (wcslen( Name ) + 1) * sizeof( WCHAR ) );
  181. }
  182. }
  183. POFFSET
  184. ImlWriteFileContents(
  185. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  186. PWSTR FileName
  187. )
  188. {
  189. HANDLE hFindFirst, hFile, hMapping;
  190. WIN32_FIND_DATA FindFileData;
  191. PVOID p;
  192. IML_FILE_RECORD_CONTENTS ImlFileContentsRecord;
  193. hFindFirst = FindFirstFile( FileName, &FindFileData );
  194. if (hFindFirst == INVALID_HANDLE_VALUE) {
  195. return 0;
  196. }
  197. FindClose( hFindFirst );
  198. ImlFileContentsRecord.LastWriteTime = FindFileData.ftLastWriteTime;
  199. ImlFileContentsRecord.FileAttributes = FindFileData.dwFileAttributes;
  200. if (!(ImlFileContentsRecord.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  201. ImlFileContentsRecord.FileSize = FindFileData.nFileSizeLow;
  202. hFile = CreateFile( FileName,
  203. GENERIC_READ,
  204. FILE_SHARE_READ,
  205. NULL,
  206. OPEN_EXISTING,
  207. 0,
  208. NULL
  209. );
  210. if (hFile == INVALID_HANDLE_VALUE) {
  211. printf( "*** CreateFile( '%ws' ) failed (%u)\n", FileName, GetLastError() );
  212. return 0;
  213. }
  214. if (ImlFileContentsRecord.FileSize != 0) {
  215. hMapping = CreateFileMapping( hFile,
  216. NULL,
  217. PAGE_READONLY,
  218. 0,
  219. 0,
  220. NULL
  221. );
  222. CloseHandle( hFile );
  223. hFile = NULL;
  224. if (hMapping == NULL) {
  225. printf( "*** CreateFileMapping( '%ws' ) failed (%u)\n", FileName, GetLastError() );
  226. return 0;
  227. }
  228. p = MapViewOfFile( hMapping,
  229. FILE_MAP_READ,
  230. 0,
  231. 0,
  232. 0
  233. );
  234. CloseHandle( hMapping );
  235. if (p == NULL) {
  236. printf( "*** MapViewOfFile( '%ws' ) failed (%u)\n", FileName, GetLastError() );
  237. return 0;
  238. }
  239. }
  240. else {
  241. CloseHandle( hFile );
  242. p = NULL;
  243. }
  244. }
  245. else {
  246. ImlFileContentsRecord.FileSize = 0;
  247. p = NULL;
  248. }
  249. ImlFileContentsRecord.Contents = ImlWrite( pIml, p, ImlFileContentsRecord.FileSize );
  250. if (p != NULL) {
  251. UnmapViewOfFile( p );
  252. }
  253. return ImlWrite( pIml,
  254. &ImlFileContentsRecord,
  255. sizeof( ImlFileContentsRecord )
  256. );
  257. }
  258. BOOLEAN
  259. ImlAddFileRecord(
  260. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  261. IML_FILE_ACTION Action,
  262. PWSTR Name,
  263. PWSTR BackupFileName,
  264. PFILETIME BackupLastWriteTime,
  265. DWORD BackupFileAttributes
  266. )
  267. {
  268. IML_FILE_RECORD ImlFileRecord;
  269. IML_FILE_RECORD_CONTENTS ImlFileContentsRecord;
  270. memset( &ImlFileRecord, 0, sizeof( ImlFileRecord ) );
  271. ImlFileRecord.Action = Action;
  272. ImlFileRecord.Name = ImlWriteString( pIml, Name );
  273. if (Action == CreateNewFile) {
  274. if ((pIml->Flags & IML_FLAG_CONTAINS_NEWFILECONTENTS) != 0) {
  275. ImlFileRecord.NewFile = ImlWriteFileContents( pIml, Name );
  276. }
  277. }
  278. else
  279. if (Action == ModifyOldFile ||
  280. Action == DeleteOldFile
  281. ) {
  282. if (BackupFileName != NULL) {
  283. ImlFileRecord.OldFile = ImlWriteFileContents( pIml, BackupFileName );
  284. }
  285. if (Action == ModifyOldFile &&
  286. (pIml->Flags & IML_FLAG_CONTAINS_NEWFILECONTENTS) != 0
  287. ) {
  288. ImlFileRecord.NewFile = ImlWriteFileContents( pIml, Name );
  289. }
  290. }
  291. else {
  292. ImlFileContentsRecord.LastWriteTime = *BackupLastWriteTime;
  293. ImlFileContentsRecord.FileAttributes = BackupFileAttributes;
  294. ImlFileContentsRecord.FileSize = 0;
  295. ImlFileContentsRecord.Contents = 0;
  296. ImlFileRecord.OldFile = ImlWrite( pIml,
  297. &ImlFileContentsRecord,
  298. sizeof( ImlFileContentsRecord )
  299. );
  300. }
  301. ImlFileRecord.Next = pIml->FileRecords;
  302. pIml->FileRecords = ImlWrite( pIml, &ImlFileRecord, sizeof( ImlFileRecord ) );
  303. pIml->NumberOfFileRecords += 1;
  304. return TRUE;
  305. }
  306. BOOLEAN
  307. ImlAddValueRecord(
  308. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  309. IML_VALUE_ACTION Action,
  310. PWSTR Name,
  311. DWORD ValueType,
  312. ULONG ValueLength,
  313. PVOID ValueData,
  314. DWORD BackupValueType,
  315. ULONG BackupValueLength,
  316. PVOID BackupValueData,
  317. POFFSET *Values
  318. )
  319. {
  320. IML_VALUE_RECORD ImlValueRecord;
  321. IML_VALUE_RECORD_CONTENTS ImlValueContentsRecord;
  322. memset( &ImlValueRecord, 0, sizeof( ImlValueRecord ) );
  323. ImlValueRecord.Action = Action;
  324. ImlValueRecord.Name = ImlWriteString( pIml, Name );
  325. if (Action != DeleteOldValue) {
  326. ImlValueContentsRecord.Type = ValueType;
  327. ImlValueContentsRecord.Length = ValueLength;
  328. ImlValueContentsRecord.Data = ImlWrite( pIml, ValueData, ValueLength );
  329. ImlValueRecord.NewValue = ImlWrite( pIml,
  330. &ImlValueContentsRecord,
  331. sizeof( ImlValueContentsRecord )
  332. );
  333. }
  334. if (Action != CreateNewValue) {
  335. ImlValueContentsRecord.Type = BackupValueType;
  336. ImlValueContentsRecord.Length = BackupValueLength;
  337. ImlValueContentsRecord.Data = ImlWrite( pIml, BackupValueData, BackupValueLength );
  338. ImlValueRecord.OldValue = ImlWrite( pIml,
  339. &ImlValueContentsRecord,
  340. sizeof( ImlValueContentsRecord )
  341. );
  342. }
  343. ImlValueRecord.Next = *Values;
  344. *Values = ImlWrite( pIml, &ImlValueRecord, sizeof( ImlValueRecord ) );
  345. return TRUE;
  346. }
  347. BOOLEAN
  348. ImlAddKeyRecord(
  349. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  350. IML_KEY_ACTION Action,
  351. PWSTR Name,
  352. POFFSET Values
  353. )
  354. {
  355. IML_KEY_RECORD ImlKeyRecord;
  356. memset( &ImlKeyRecord, 0, sizeof( ImlKeyRecord ) );
  357. ImlKeyRecord.Action = Action;
  358. ImlKeyRecord.Name = ImlWriteString( pIml, Name );
  359. ImlKeyRecord.Values = Values;
  360. ImlKeyRecord.Next = pIml->KeyRecords;
  361. pIml->KeyRecords = ImlWrite( pIml, &ImlKeyRecord, sizeof( ImlKeyRecord ) );
  362. pIml->NumberOfKeyRecords += 1;
  363. return TRUE;
  364. }
  365. BOOLEAN
  366. ImlAddIniVariableRecord(
  367. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  368. IML_INIVARIABLE_ACTION Action,
  369. PWSTR Name,
  370. PWSTR OldValue,
  371. PWSTR NewValue,
  372. POFFSET *Variables
  373. )
  374. {
  375. IML_INIVARIABLE_RECORD ImlIniVariableRecord;
  376. memset( &ImlIniVariableRecord, 0, sizeof( ImlIniVariableRecord ) );
  377. ImlIniVariableRecord.Action = Action;
  378. ImlIniVariableRecord.Name = ImlWriteString( pIml, Name );
  379. ImlIniVariableRecord.OldValue = ImlWriteString( pIml, OldValue );
  380. ImlIniVariableRecord.NewValue = ImlWriteString( pIml, NewValue );
  381. ImlIniVariableRecord.Next = *Variables;
  382. *Variables = ImlWrite( pIml, &ImlIniVariableRecord, sizeof( ImlIniVariableRecord ) );
  383. return TRUE;
  384. }
  385. BOOLEAN
  386. ImlAddIniSectionRecord(
  387. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  388. IML_INISECTION_ACTION Action,
  389. PWSTR Name,
  390. POFFSET Variables,
  391. POFFSET *Sections
  392. )
  393. {
  394. IML_INISECTION_RECORD ImlIniSectionRecord;
  395. memset( &ImlIniSectionRecord, 0, sizeof( ImlIniSectionRecord ) );
  396. ImlIniSectionRecord.Action = Action;
  397. ImlIniSectionRecord.Name = ImlWriteString( pIml, Name );
  398. ImlIniSectionRecord.Variables = Variables;
  399. ImlIniSectionRecord.Next = *Sections;
  400. *Sections = ImlWrite( pIml, &ImlIniSectionRecord, sizeof( ImlIniSectionRecord ) );
  401. return TRUE;
  402. }
  403. BOOLEAN
  404. ImlAddIniRecord(
  405. PINSTALLATION_MODIFICATION_LOGFILE pIml,
  406. IML_INI_ACTION Action,
  407. PWSTR Name,
  408. PFILETIME BackupLastWriteTime,
  409. POFFSET Sections
  410. )
  411. {
  412. IML_INI_RECORD ImlIniRecord;
  413. memset( &ImlIniRecord, 0, sizeof( ImlIniRecord ) );
  414. ImlIniRecord.Action = Action;
  415. ImlIniRecord.Name = ImlWriteString( pIml, Name );
  416. ImlIniRecord.LastWriteTime = *BackupLastWriteTime;
  417. ImlIniRecord.Sections = Sections;
  418. ImlIniRecord.Next = pIml->IniRecords;
  419. pIml->IniRecords = ImlWrite( pIml, &ImlIniRecord, sizeof( ImlIniRecord ) );
  420. pIml->NumberOfIniRecords += 1;
  421. return TRUE;
  422. }