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.

440 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. file.c
  5. Abstract:
  6. This module implements the functions to save references to files for the
  7. INSTALER program. Part of each reference is a handle to a backup copy
  8. of a file if the reference is a write/delete/rename.
  9. Author:
  10. Steve Wood (stevewo) 22-Aug-1994
  11. Revision History:
  12. --*/
  13. #include "instaler.h"
  14. BOOLEAN
  15. CreateFileReference(
  16. PWSTR Name,
  17. BOOLEAN WriteAccess,
  18. PFILE_REFERENCE *ReturnedReference
  19. )
  20. {
  21. PFILE_REFERENCE p;
  22. PWSTR BackupFileName;
  23. WIN32_FIND_DATAW FindFileData;
  24. HANDLE FindFileHandle;
  25. *ReturnedReference = NULL;
  26. p = FindFileReference( Name );
  27. if (p != NULL) {
  28. if (p->WriteAccess) {
  29. *ReturnedReference = p;
  30. return TRUE;
  31. }
  32. }
  33. else {
  34. p = AllocMem( sizeof( *p ) );
  35. if (p == NULL) {
  36. return FALSE;
  37. }
  38. InsertTailList( &FileReferenceListHead, &p->Entry );
  39. NumberOfFileReferences += 1;
  40. p->Name = Name;
  41. }
  42. BackupFileName = L"";
  43. FindFileHandle = NULL;
  44. if ((p->WriteAccess = WriteAccess) &&
  45. (FindFileHandle = FindFirstFileW( p->Name, &FindFileData )) != INVALID_HANDLE_VALUE
  46. ) {
  47. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  48. p->DirectoryFile = TRUE;
  49. }
  50. else {
  51. p->BackupFileAttributes = FindFileData.dwFileAttributes;
  52. p->BackupLastWriteTime = FindFileData.ftLastWriteTime;
  53. p->BackupFileSize.LowPart = FindFileData.nFileSizeLow;
  54. p->BackupFileSize.HighPart = FindFileData.nFileSizeHigh;
  55. BackupFileName = CreateBackupFileName( &p->BackupFileUniqueId );
  56. if (BackupFileName == NULL ||
  57. !CopyFileW( Name, BackupFileName, TRUE )
  58. ) {
  59. p->BackupFileUniqueId = 0xFFFF; // Backup failed.
  60. DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), Name );
  61. }
  62. }
  63. }
  64. else {
  65. p->Created = p->WriteAccess;
  66. }
  67. if (FindFileHandle != NULL) {
  68. FindClose( FindFileHandle );
  69. }
  70. *ReturnedReference = p;
  71. return TRUE;
  72. }
  73. BOOLEAN
  74. CompleteFileReference(
  75. PFILE_REFERENCE p,
  76. BOOLEAN CallSuccessful,
  77. BOOLEAN Deleted,
  78. PFILE_REFERENCE RenameReference
  79. )
  80. {
  81. DWORD dwFileAttributes;
  82. if (!CallSuccessful) {
  83. DestroyFileReference( p );
  84. return FALSE;
  85. }
  86. if (RenameReference) {
  87. if (RenameReference->Created) {
  88. LogEvent( INSTALER_EVENT_RENAME_TEMP_FILE,
  89. 3,
  90. RenameReference->DirectoryFile ? L"directory" : L"file",
  91. RenameReference->Name,
  92. p->Name
  93. );
  94. RenameReference->Name = p->Name;
  95. DestroyFileReference( p );
  96. return FALSE;
  97. }
  98. RenameReference->Deleted = TRUE;
  99. LogEvent( INSTALER_EVENT_RENAME_FILE,
  100. 3,
  101. RenameReference->DirectoryFile ? L"directory" : L"file",
  102. RenameReference->Name,
  103. p->Name
  104. );
  105. }
  106. else
  107. if (Deleted && p->Created) {
  108. LogEvent( INSTALER_EVENT_DELETE_TEMP_FILE,
  109. 2,
  110. p->DirectoryFile ? L"directory" : L"file",
  111. p->Name
  112. );
  113. DestroyFileReference( p );
  114. return FALSE;
  115. }
  116. else {
  117. if (wcschr( p->Name, '\\' ) == NULL) {
  118. //
  119. // If no path separator, must be volume open. Treat
  120. // as directory and dont touch file
  121. //
  122. p->DirectoryFile = TRUE;
  123. }
  124. else
  125. if ((dwFileAttributes = GetFileAttributes( p->Name )) != 0xFFFFFFFF) {
  126. p->DirectoryFile = (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  127. }
  128. if (Deleted) {
  129. LogEvent( INSTALER_EVENT_DELETE_FILE,
  130. 2,
  131. p->DirectoryFile ? L"directory" : L"file",
  132. p->Name
  133. );
  134. }
  135. else
  136. if (p->WriteAccess) {
  137. if (p->Created) {
  138. LogEvent( INSTALER_EVENT_CREATE_FILE,
  139. 2,
  140. p->DirectoryFile ? L"directory" : L"file",
  141. p->Name
  142. );
  143. }
  144. else {
  145. LogEvent( INSTALER_EVENT_WRITE_FILE,
  146. 2,
  147. p->DirectoryFile ? L"directory" : L"file",
  148. p->Name
  149. );
  150. }
  151. }
  152. else {
  153. LogEvent( INSTALER_EVENT_READ_FILE,
  154. 2,
  155. p->DirectoryFile ? L"directory" : L"file",
  156. p->Name
  157. );
  158. }
  159. }
  160. p->Deleted = Deleted;
  161. return TRUE;
  162. }
  163. BOOLEAN
  164. DestroyFileReference(
  165. PFILE_REFERENCE p
  166. )
  167. {
  168. PWSTR BackupFileName;
  169. if (!p->Created &&
  170. (BackupFileName = FormatTempFileName( NULL, &p->BackupFileUniqueId ))
  171. ) {
  172. DeleteFileW( BackupFileName );
  173. }
  174. if (p->DateModified || p->AttributesModified) {
  175. return FALSE;
  176. }
  177. RemoveEntryList( &p->Entry );
  178. NumberOfFileReferences -= 1;
  179. FreeMem( &p );
  180. return TRUE;
  181. }
  182. PVOID
  183. MapFileForRead(
  184. PWSTR FileName,
  185. PULONG FileSize
  186. )
  187. {
  188. HANDLE FileHandle, MappingHandle;
  189. PVOID FileData;
  190. ULONG HighFileSize;
  191. FileData = NULL;
  192. FileHandle = CreateFileW( FileName,
  193. GENERIC_READ,
  194. FILE_SHARE_READ | FILE_SHARE_WRITE,
  195. NULL,
  196. OPEN_EXISTING,
  197. 0,
  198. NULL
  199. );
  200. if (FileHandle != INVALID_HANDLE_VALUE) {
  201. *FileSize = GetFileSize( FileHandle, &HighFileSize );
  202. if (*FileSize == 0) {
  203. CloseHandle( FileHandle );
  204. return (PVOID)0xFFFFFFFF;
  205. }
  206. MappingHandle = CreateFileMappingW( FileHandle,
  207. NULL,
  208. PAGE_READONLY,
  209. 0,
  210. *FileSize,
  211. NULL
  212. );
  213. CloseHandle( FileHandle );
  214. if (MappingHandle != NULL) {
  215. FileData = MapViewOfFile( MappingHandle,
  216. FILE_MAP_READ,
  217. 0,
  218. 0,
  219. *FileSize
  220. );
  221. CloseHandle( MappingHandle );
  222. }
  223. }
  224. return FileData;
  225. }
  226. BOOLEAN
  227. AreFileContentsEqual(
  228. PWSTR FileName1,
  229. PWSTR FileName2
  230. )
  231. {
  232. PVOID FileData1, FileData2;
  233. ULONG FileSize1, FileSize2;
  234. BOOLEAN Result;
  235. Result = FALSE;
  236. if (FileData1 = MapFileForRead( FileName1, &FileSize1 )) {
  237. if (FileData2 = MapFileForRead( FileName2, &FileSize2 )) {
  238. if (FileSize1 == FileSize2 &&
  239. RtlCompareMemory( FileData1, FileData2, FileSize1 ) == FileSize1
  240. ) {
  241. Result = TRUE;
  242. }
  243. if (FileData2 != (PVOID)0xFFFFFFFF) {
  244. UnmapViewOfFile( FileData2 );
  245. }
  246. }
  247. else {
  248. DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), FileName2 );
  249. }
  250. if (FileData1 != (PVOID)0xFFFFFFFF) {
  251. UnmapViewOfFile( FileData1 );
  252. }
  253. }
  254. else {
  255. DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), FileName1 );
  256. }
  257. return Result;
  258. }
  259. BOOLEAN
  260. IsNewFileSameAsBackup(
  261. PFILE_REFERENCE p
  262. )
  263. {
  264. WIN32_FIND_DATAW FindFileData;
  265. HANDLE FindFileHandle;
  266. PWSTR BackupFileName;
  267. if ((FindFileHandle = FindFirstFileW( p->Name, &FindFileData )) != INVALID_HANDLE_VALUE) {
  268. FindClose( FindFileHandle );
  269. if (p->BackupFileAttributes != FindFileData.dwFileAttributes) {
  270. p->AttributesModified = TRUE;
  271. }
  272. if (p->BackupLastWriteTime.dwLowDateTime != FindFileData.ftLastWriteTime.dwLowDateTime ||
  273. p->BackupLastWriteTime.dwHighDateTime != FindFileData.ftLastWriteTime.dwHighDateTime
  274. ) {
  275. p->DateModified = TRUE;
  276. }
  277. if (BackupFileName = FormatTempFileName( NULL, &p->BackupFileUniqueId )) {
  278. if (p->BackupFileSize.LowPart != FindFileData.nFileSizeLow ||
  279. p->BackupFileSize.HighPart != FindFileData.nFileSizeHigh ||
  280. !AreFileContentsEqual( BackupFileName, p->Name )
  281. ) {
  282. p->ContentsModified = TRUE;
  283. return FALSE;
  284. }
  285. }
  286. return TRUE;
  287. }
  288. else {
  289. return FALSE;
  290. }
  291. }
  292. PFILE_REFERENCE
  293. FindFileReference(
  294. PWSTR Name
  295. )
  296. {
  297. PFILE_REFERENCE p;
  298. PLIST_ENTRY Head, Next;
  299. Head = &FileReferenceListHead;
  300. Next = Head->Flink;
  301. while (Head != Next) {
  302. p = CONTAINING_RECORD( Next, FILE_REFERENCE, Entry );
  303. if (p->Name == Name) {
  304. return p;
  305. }
  306. Next = Next->Flink;
  307. }
  308. return NULL;
  309. }
  310. VOID
  311. DumpFileReferenceList(
  312. FILE *LogFile
  313. )
  314. {
  315. PFILE_REFERENCE p;
  316. PLIST_ENTRY Head, Next;
  317. Head = &FileReferenceListHead;
  318. Next = Head->Flink;
  319. while (Head != Next) {
  320. p = CONTAINING_RECORD( Next, FILE_REFERENCE, Entry );
  321. if (p->WriteAccess) {
  322. if (!p->Deleted) {
  323. if (p->BackupFileUniqueId == 0) {
  324. if (p->Created) {
  325. ImlAddFileRecord( pImlNew,
  326. CreateNewFile,
  327. p->Name,
  328. NULL,
  329. NULL,
  330. 0
  331. );
  332. }
  333. }
  334. else {
  335. if (p->ContentsModified) {
  336. if (ImlAddFileRecord( pImlNew,
  337. ModifyOldFile,
  338. p->Name,
  339. FormatTempFileName( NULL, &p->BackupFileUniqueId ),
  340. NULL,
  341. 0
  342. )
  343. ) {
  344. DeleteFile( FormatTempFileName( NULL, &p->BackupFileUniqueId ) );
  345. }
  346. }
  347. else
  348. if (p->DateModified) {
  349. ImlAddFileRecord( pImlNew,
  350. ModifyFileDateTime,
  351. p->Name,
  352. NULL,
  353. &p->BackupLastWriteTime,
  354. p->BackupFileAttributes
  355. );
  356. }
  357. else {
  358. ImlAddFileRecord( pImlNew,
  359. ModifyFileAttributes,
  360. p->Name,
  361. NULL,
  362. &p->BackupLastWriteTime,
  363. p->BackupFileAttributes
  364. );
  365. }
  366. }
  367. }
  368. else {
  369. if (ImlAddFileRecord( pImlNew,
  370. DeleteOldFile,
  371. p->Name,
  372. FormatTempFileName( NULL, &p->BackupFileUniqueId ),
  373. NULL,
  374. 0
  375. )
  376. ) {
  377. DeleteFile( FormatTempFileName( NULL, &p->BackupFileUniqueId ) );
  378. }
  379. }
  380. }
  381. Next = Next->Flink;
  382. }
  383. return;
  384. }