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.

354 lines
11 KiB

  1. /*****************************************************************************************************************
  2. FILENAME: DasdRead.cpp
  3. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  4. OVERVIEW:
  5. Routines for reading directly from the disk.
  6. */
  7. #include "stdafx.h"
  8. #ifdef BOOTIME
  9. extern "C" {
  10. #include <stdio.h>
  11. }
  12. #include "Offline.h"
  13. #else
  14. #include <windows.h>
  15. #endif
  16. extern "C" {
  17. #include "SysStruc.h"
  18. }
  19. #include "ErrMacro.h"
  20. #include "DfrgCmn.h"
  21. #include "DfrgEngn.h"
  22. #include "Alloc.h"
  23. #include "Message.h"
  24. /*****************************************************************************************************************
  25. ROUTINE: DasdLoadSectors
  26. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  27. ROUTINE DESCRIPTION:
  28. This routine allocates a buffer and fills it with sectors read from a disk.
  29. NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
  30. this is because this routine will align the read on a sector boundary, and this may temporarily
  31. shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
  32. INPUT + OUTPUT:
  33. IN hVolume - A handle to the volume to read sectors from.
  34. IN Sector - Sector to start reading from.
  35. IN Sectors - Number of sectors to read.
  36. IN BytesPerSector - The number of bytes in a sector.
  37. RETURN:
  38. Handle to the memory that the sectors were read into.
  39. NULL = Failure
  40. */
  41. HANDLE
  42. DasdLoadSectors(
  43. IN HANDLE hVolume,
  44. IN LONGLONG Sector,
  45. IN LONGLONG Sectors,
  46. IN LONGLONG BytesPerSector
  47. )
  48. {
  49. HANDLE hBuffer = NULL;
  50. LPBYTE pBuffer = NULL;
  51. LONGLONG BufferSize = Sectors * BytesPerSector;
  52. LONGLONG ByteOffset = Sector * BytesPerSector;
  53. LONGLONG AllocSize = BufferSize + BytesPerSector;
  54. LPBYTE pLoad = NULL;
  55. OVERLAPPED Seek = {0};
  56. DWORD Read = 0;
  57. BOOL bOk = FALSE;
  58. //0.0E00 Error if we were requested to read nothing.
  59. if (BufferSize == 0){
  60. EH(FALSE);
  61. return (HANDLE) NULL;
  62. }
  63. //0.0E00 Allocate and lock a buffer; allocate 1 sector more than needed for alignment
  64. if (!AllocateMemory((DWORD) AllocSize, &hBuffer, (PVOID*) &pBuffer)){
  65. EH(FALSE);
  66. return (HANDLE) NULL;
  67. }
  68. __try{
  69. //0.0E00 Sector align the buffer for DASD read
  70. pLoad = pBuffer;
  71. if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
  72. pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
  73. }
  74. //0.0E00 Set the seek address
  75. *(PLONGLONG)(&Seek.Offset) = ByteOffset;
  76. Seek.hEvent = NULL;
  77. //0.0E00 Read the sectors
  78. if (!ReadFile(hVolume, pLoad, (DWORD)BufferSize, &Read, &Seek)){
  79. EH_ASSERT(FALSE);
  80. __leave;
  81. }
  82. //0.0E00 De-align the data back to the start of the buffer
  83. if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
  84. MoveMemory(pBuffer, pLoad, (DWORD)BufferSize);
  85. ZeroMemory(pBuffer + BufferSize, (DWORD)(AllocSize - BufferSize));
  86. }
  87. bOk = TRUE;
  88. }
  89. __finally{
  90. // if not OK, delete the memory and null the handle
  91. if (!bOk){
  92. if (hBuffer){
  93. EH_ASSERT(GlobalUnlock(hBuffer) == FALSE);
  94. EH_ASSERT(GlobalFree(hBuffer) == NULL);
  95. }
  96. hBuffer = NULL;
  97. }
  98. }
  99. return hBuffer;
  100. }
  101. /*****************************************************************************************************************
  102. ROUTINE: DasdStoreSectors
  103. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  104. ROUTINE DESCRIPTION:
  105. This routine stores a buffer to sectors on a disk.
  106. NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
  107. this is because this routine will align the read on a sector boundary, and this may temporarily
  108. shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
  109. INPUT + OUTPUT:
  110. IN hVolume - A handle to the volume to read sectors from.
  111. IN Sector - Sector to start reading from.
  112. IN Sectors - Number of sectors to read.
  113. IN BytesPerSector - The number of bytes in a sector.
  114. IN pBuffer - The buffer to write to the disk.
  115. RETURN:
  116. TRUE = Success
  117. FALSE = Failure
  118. */
  119. BOOL
  120. DasdStoreSectors(
  121. IN HANDLE hVolume,
  122. IN LONGLONG Sector,
  123. IN LONGLONG Sectors,
  124. IN LONGLONG BytesPerSector,
  125. IN LPBYTE pBuffer
  126. )
  127. {
  128. LONGLONG BufferSize = Sectors * BytesPerSector;
  129. LONGLONG ByteOffset = Sector * BytesPerSector;
  130. LPBYTE pLoad = NULL;
  131. OVERLAPPED Seek = {0};
  132. DWORD Read = 0;
  133. BOOL bStatus = FALSE;
  134. //0.0E00 Error if we were requested to write nothing.
  135. EF_ASSERT(BufferSize != 0);
  136. //0.0E00 Sector align the buffer for DASD write
  137. pLoad = pBuffer;
  138. if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
  139. pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
  140. MoveMemory(pLoad, pBuffer, (DWORD)BufferSize);
  141. }
  142. //0.0E00 Set the seek address
  143. *(PLONGLONG)(&Seek.Offset) = ByteOffset;
  144. Seek.hEvent = NULL;
  145. //0.0E00 Read the sectors
  146. EF_ASSERT(WriteFile(hVolume, pLoad, (DWORD)BufferSize, &Read, &Seek));
  147. //0.0E00 De-align the data back to the start of the buffer
  148. if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
  149. MoveMemory(pBuffer, pLoad, (DWORD)BufferSize);
  150. ZeroMemory(pBuffer + BufferSize, (DWORD)(pLoad - pBuffer));
  151. }
  152. return TRUE;
  153. }
  154. /*****************************************************************************************************************
  155. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  156. ROUTINE DESCRIPTION:
  157. This routine reads clusters from a disk into a memory buffer.
  158. NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
  159. this is because this routine will align the read on a sector boundary, and this may temporarily
  160. shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
  161. INPUT + OUTPUT:
  162. IN hVolume - A handle to the volume to read sectors from.
  163. IN Cluster - Cluster to start reading from.
  164. IN Clusters - Number of clusters to read.
  165. OUT pBuffer - Where the clusters will be written into memory.
  166. IN BytesPerSector - The number of bytes in a sector.
  167. IN BytesPerCluster - The number of bytes in a cluster.
  168. RETURN:
  169. TRUE = Success
  170. FALSE = Failure
  171. */
  172. BOOL
  173. DasdReadClusters(
  174. IN HANDLE hVolume,
  175. IN LONGLONG Cluster,
  176. IN LONGLONG Clusters,
  177. IN PVOID pBuffer,
  178. IN LONGLONG BytesPerSector,
  179. IN LONGLONG BytesPerCluster
  180. )
  181. {
  182. LONGLONG ByteOffset = Cluster * BytesPerCluster;
  183. LONGLONG ByteLength = Clusters * BytesPerCluster;
  184. LONGLONG FullLength = ByteLength + BytesPerSector;
  185. LPBYTE pLoad = NULL;
  186. OVERLAPPED Seek;
  187. DWORD Read = 0;
  188. //0.0E00 Error if requested to read nothing.
  189. EF_ASSERT(ByteLength != 0);
  190. //Zero out the seek parameter.
  191. ZeroMemory(&Seek, sizeof(OVERLAPPED));
  192. //On FAT, or FAT32, we have to bump the offset up since the "clusters" don't start until after the boot
  193. //block and the FAT's.
  194. if(VolData.FileSystem == FS_FAT || VolData.FileSystem == FS_FAT32){
  195. ByteOffset += VolData.FirstDataOffset;
  196. }
  197. //0.0E00 Sector align the buffer for DASD read
  198. pLoad = (LPBYTE)pBuffer;
  199. if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
  200. pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
  201. }
  202. //0.0E00 Set the seek address
  203. *(PLONGLONG)(&Seek.Offset) = ByteOffset;
  204. Seek.hEvent = NULL;
  205. //DURING INTEGRATION BETWEEN DKMS AND OFFLINE, I DIDN'T KNOW IF THE WSPRINTF AND ERROR STUFF IS NECESSARY.
  206. //SO I PUT IT IN AS WELL AS THE EF_ASSERT.
  207. //0.0E00 Read the clusters
  208. // EF_ASSERT(ReadFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek));
  209. if(!ReadFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek)){
  210. TCHAR cOutline[200];
  211. wsprintf (cOutline,
  212. TEXT("ReadFile: Handle=0x%08lx, pLoad=0x%08lx, ByteLength=0x%08lx, Offset=0x%08lx, Cluster=0x%08lx\n"),
  213. hVolume,
  214. pLoad,
  215. (DWORD)ByteLength,
  216. (LONG) ByteOffset,
  217. (LONG) Cluster);
  218. Message (cOutline, GetLastError(), NULL);
  219. EF(FALSE);
  220. }
  221. //0.0E00 De-align the data back to the start of the buffer
  222. if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
  223. MoveMemory(pBuffer, pLoad, (DWORD)ByteLength);
  224. ZeroMemory((char*)pBuffer + ByteLength, (DWORD)(FullLength - ByteLength));
  225. }
  226. return TRUE;
  227. }
  228. /*****************************************************************************************************************
  229. ROUTINE: DasdWriteClusters
  230. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  231. ROUTINE DESCRIPTION:
  232. This routine writes clusters from a disk into a memory buffer.
  233. NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
  234. this is because this routine will align the read on a sector boundary, and this may temporarily
  235. shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
  236. INPUT + OUTPUT:
  237. IN hVolume - A handle to the volume to read sectors from.
  238. IN Cluster - Cluster to start reading from.
  239. IN Clusters - Number of clusters to read.
  240. OUT pBuffer - Where the clusters will be written into memory.
  241. IN BytesPerSector - The number of bytes in a sector.
  242. IN BytesPerCluster - The number of bytes in a cluster.
  243. RETURN:
  244. TRUE = Success
  245. FALSE = Failure
  246. */
  247. BOOL
  248. DasdWriteClusters(
  249. IN HANDLE hVolume,
  250. IN LONGLONG Cluster,
  251. IN LONGLONG Clusters,
  252. IN PVOID pBuffer,
  253. IN LONGLONG BytesPerSector,
  254. IN LONGLONG BytesPerCluster
  255. )
  256. {
  257. LONGLONG ByteOffset = Cluster * BytesPerCluster;
  258. LONGLONG ByteLength = Clusters * BytesPerCluster;
  259. LONGLONG FullLength = ByteLength + BytesPerSector;
  260. LPBYTE pLoad = NULL;
  261. OVERLAPPED Seek;
  262. DWORD Read = 0;
  263. //0.0E00 Error if requested to write nothing.
  264. EF_ASSERT(ByteLength != 0);
  265. //Zero out the seek parameter.
  266. ZeroMemory(&Seek, sizeof(OVERLAPPED));
  267. //On FAT, or FAT32, we have to bump the offset up since the "clusters" don't start until after the boot
  268. //block and the FAT's.
  269. if(VolData.FileSystem == FS_FAT || VolData.FileSystem == FS_FAT32){
  270. ByteOffset += VolData.FirstDataOffset;
  271. }
  272. //0.0E00 Sector align the buffer for DASD write
  273. pLoad = (LPBYTE)pBuffer;
  274. if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
  275. pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
  276. MoveMemory(pLoad, pBuffer, (DWORD)ByteLength);
  277. }
  278. //0.0E00 Set the seek address
  279. *(PLONGLONG)(&Seek.Offset) = ByteOffset;
  280. Seek.hEvent = NULL;
  281. //0.0E00 Write the clusters
  282. EF_ASSERT(WriteFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek));
  283. //0.0E00 De-align the data back to the start of the buffer
  284. if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
  285. MoveMemory(pBuffer, pLoad, (DWORD)ByteLength);
  286. ZeroMemory((char*)pBuffer + ByteLength, (DWORD)(FullLength - ByteLength));
  287. }
  288. return TRUE;
  289. }