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.

565 lines
9.5 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. All rights reserved.
  4. Module Name:
  5. Stream.cxx
  6. Abstract:
  7. implements TStream class methods
  8. Author:
  9. Adina Trufinescu (AdinaTru) 4-Nov-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "stream.hxx"
  15. /*++
  16. Title:
  17. TStream
  18. Routine Description:
  19. Initialize the TStream class; note the class is initaliy
  20. in an in valid state until a read or write occurs in which
  21. case the file handle is created and then the class becomes valid.
  22. Arguments:
  23. None
  24. Return Value:
  25. Nothing
  26. --*/
  27. TStream::
  28. TStream(
  29. IN TString& strFileName
  30. ) : m_strFileName(strFileName),
  31. m_hFileHandle(INVALID_HANDLE_VALUE),
  32. m_dwAccess(0),
  33. m_bCreated(FALSE)
  34. {
  35. m_uliStreamSize.QuadPart = 0;
  36. }
  37. /*++
  38. Title:
  39. ~TStream
  40. Routine Description:
  41. Releases the stream file handle.
  42. Arguments:
  43. None
  44. Return Value:
  45. Nothing
  46. --*/
  47. TStream::
  48. ~TStream(
  49. VOID
  50. )
  51. {
  52. if(m_hFileHandle != INVALID_HANDLE_VALUE)
  53. {
  54. CloseHandle(m_hFileHandle);
  55. }
  56. }
  57. /*++
  58. Title:
  59. bValid
  60. Routine Description:
  61. check class member validity : file handle invalid
  62. Arguments:
  63. None
  64. Return Value:
  65. TRUE if class is in a valid state.
  66. --*/
  67. BOOL
  68. TStream::
  69. bValid(
  70. VOID
  71. )
  72. {
  73. return (m_hFileHandle != INVALID_HANDLE_VALUE);
  74. }
  75. /*++
  76. Title:
  77. Read
  78. Routine Description:
  79. Reads cb bytes into pv , from current position of file.
  80. Number of actual reded bytes stored in pbcRead
  81. Arguments:
  82. Return Value:
  83. The error code from ReadFile API is converted to HRESULT
  84. --*/
  85. HRESULT
  86. TStream::
  87. Read(
  88. VOID *pv,
  89. ULONG cb,
  90. ULONG *pcbRead
  91. )
  92. {
  93. TStatusH hr;
  94. if(!bValid())
  95. {
  96. m_hFileHandle = PCreateFile(&m_dwAccess);
  97. if(!bValid())
  98. {
  99. hr DBGCHK = E_UNEXPECTED;
  100. goto End;
  101. }
  102. }
  103. if(bValid())
  104. {
  105. if(pv)
  106. {
  107. if(!ReadFile( m_hFileHandle,
  108. reinterpret_cast<LPDWORD>(pv),
  109. static_cast<DWORD>(cb),
  110. reinterpret_cast<LPDWORD>(pcbRead),
  111. NULL))
  112. {
  113. *pcbRead = 0;
  114. hr DBGCHK = MapWin32ErrorCodeToHRes(GetLastError());
  115. goto End;
  116. }
  117. hr DBGCHK = ((*pcbRead) == cb) && (*pcbRead != 0 && cb != 0) ? S_OK : E_FAIL;
  118. }
  119. else
  120. {
  121. hr DBGCHK = STG_E_INVALIDPOINTER;
  122. }
  123. }
  124. End:
  125. return hr;
  126. }
  127. /*++
  128. Title:
  129. Write
  130. Routine Description:
  131. Writes cb bytes from pv , at current position of file.
  132. Number of actual written bytes stored in pcbWritten
  133. Arguments:
  134. Return Value:
  135. The error code from WriteFile API is converted to HRESULT
  136. --*/
  137. HRESULT
  138. TStream::
  139. Write(
  140. VOID const* pv,
  141. ULONG cb,
  142. ULONG * pcbWritten
  143. )
  144. {
  145. HRESULT hr = E_UNEXPECTED;
  146. if(!bValid())
  147. {
  148. m_hFileHandle = PCreateFile(&m_dwAccess);
  149. if(!bValid())
  150. {
  151. goto End;
  152. }
  153. }
  154. if(bValid())
  155. {
  156. if(pv)
  157. {
  158. if(!WriteFile(m_hFileHandle,
  159. static_cast<LPCVOID>(pv),
  160. static_cast<DWORD>(cb),
  161. reinterpret_cast<LPDWORD>(pcbWritten),
  162. NULL))
  163. {
  164. if (pcbWritten)
  165. {
  166. *pcbWritten = 0;
  167. }
  168. hr = MapWin32ErrorCodeToHRes(GetLastError());
  169. }
  170. if (pcbWritten)
  171. {
  172. hr = (*pcbWritten == cb) ? S_OK : hr;
  173. }
  174. else
  175. {
  176. hr = STG_E_INVALIDPOINTER;
  177. }
  178. if(SUCCEEDED(hr))
  179. {
  180. DBGMSG( DBG_NONE, ( "TPrnStream::Write OK !!!\n" ));
  181. }
  182. }
  183. else
  184. {
  185. hr = STG_E_INVALIDPOINTER;
  186. }
  187. }
  188. End:
  189. return hr;
  190. }
  191. /*++
  192. Title:
  193. Seek
  194. Routine Description:
  195. Set stream pointer
  196. Arguments:
  197. dlibMove - Offset relative to dwOrigin
  198. dwOrigin - Specifies the origin for the offset
  199. plibNewPosition - Pointer to location containing new seek
  200. Return Value:
  201. The error code from SetFilePointer API is converted to HRESULT
  202. --*/
  203. HRESULT
  204. TStream::
  205. Seek(
  206. LARGE_INTEGER dlibMove,
  207. DWORD dwOrigin,
  208. ULARGE_INTEGER * plibNewPosition
  209. )
  210. {
  211. DWORD dwMoveMethod;
  212. DWORD dwCurrentFilePosition ;
  213. LONG lDistanceToMoveHigh;
  214. TStatusB bStatus;
  215. TStatusH hr;
  216. DWORD dwError;
  217. static const DWORD adwMoveMethode[] =
  218. {
  219. FILE_BEGIN,
  220. FILE_CURRENT,
  221. FILE_END,
  222. };
  223. dwMoveMethod = adwMoveMethode[dwOrigin];
  224. if(!bValid())
  225. {
  226. m_hFileHandle = PCreateFile(&m_dwAccess);
  227. if(!bValid())
  228. {
  229. hr DBGCHK = E_UNEXPECTED;
  230. goto End;
  231. }
  232. }
  233. lDistanceToMoveHigh = dlibMove.HighPart;
  234. dwCurrentFilePosition = SetFilePointer( m_hFileHandle,
  235. static_cast<LONG>(dlibMove.LowPart),
  236. &lDistanceToMoveHigh,
  237. dwMoveMethod );
  238. DBGMSG( DBG_NONE, ( "Seek: Current pos: high %d low %d\n" ,lDistanceToMoveHigh, dwCurrentFilePosition) );
  239. if (dwCurrentFilePosition == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR )
  240. {
  241. hr DBGCHK = MapWin32ErrorCodeToHRes(dwError);
  242. }
  243. else
  244. {
  245. if(plibNewPosition)
  246. {
  247. plibNewPosition->HighPart = static_cast<DWORD>(lDistanceToMoveHigh);
  248. plibNewPosition->LowPart = dwCurrentFilePosition;
  249. }
  250. hr DBGNOCHK = S_OK;
  251. }
  252. End:
  253. return hr;
  254. }
  255. /*++
  256. Title:
  257. PCreateFile
  258. Routine Description:
  259. If file doesn't exists , create it with write / read access
  260. If file exists , try open it with read wrire access ; if fail , try to open with read
  261. Arguments:
  262. pdwAccess - access rights if succeeded , 0 if failed
  263. Return Value:
  264. The error code from SetFilePointer API is converted to HRESULT
  265. --*/
  266. HANDLE
  267. TStream::
  268. PCreateFile(
  269. OUT LPDWORD pdwAccess
  270. )
  271. {
  272. HANDLE hFileHandle;
  273. DWORD dwAccess;
  274. *pdwAccess = 0;
  275. //
  276. // try to open an existing file with read/write access
  277. //
  278. dwAccess = GENERIC_WRITE | GENERIC_READ;
  279. hFileHandle = CreateFile( m_strFileName,
  280. dwAccess,
  281. 0,
  282. NULL,
  283. OPEN_EXISTING,
  284. FILE_ATTRIBUTE_NORMAL,
  285. NULL);
  286. if(hFileHandle == INVALID_HANDLE_VALUE)
  287. {
  288. //
  289. // if last error is access denied , try to open only with read access
  290. //
  291. if(GetLastError() == ERROR_ACCESS_DENIED)
  292. {
  293. dwAccess = GENERIC_READ;
  294. hFileHandle = CreateFile( m_strFileName,
  295. GENERIC_READ,
  296. 0,
  297. NULL,
  298. OPEN_EXISTING,
  299. FILE_ATTRIBUTE_NORMAL,
  300. NULL);
  301. }
  302. else if(GetLastError() == ERROR_FILE_NOT_FOUND)
  303. {
  304. dwAccess = GENERIC_WRITE | GENERIC_READ;
  305. //
  306. // if last error was file don't exist , try to create it
  307. //
  308. hFileHandle = CreateFile( m_strFileName,
  309. dwAccess,
  310. 0,
  311. NULL,
  312. OPEN_ALWAYS,
  313. FILE_ATTRIBUTE_NORMAL,
  314. NULL);
  315. m_bCreated = TRUE;
  316. }
  317. }
  318. if(hFileHandle != INVALID_HANDLE_VALUE)
  319. {
  320. *pdwAccess = dwAccess;
  321. m_uliStreamSize.LowPart = GetFileSize(hFileHandle, &m_uliStreamSize.HighPart);
  322. }
  323. return hFileHandle;
  324. }
  325. /*++
  326. Title:
  327. DestroyFile
  328. Routine Description:
  329. If file handle is invalid , it means that file wasn't creaded - return TRUE
  330. If file handle is valid , close it and delete file
  331. Arguments:
  332. None
  333. Return Value:
  334. TRUE if succeeded
  335. --*/
  336. HRESULT
  337. TStream::
  338. DestroyFile(
  339. VOID
  340. )
  341. {
  342. TStatusB bStatus;
  343. bStatus DBGNOCHK = TRUE;
  344. if(m_hFileHandle != INVALID_HANDLE_VALUE)
  345. {
  346. CloseHandle(m_hFileHandle);
  347. m_hFileHandle = INVALID_HANDLE_VALUE;
  348. bStatus DBGCHK = DeleteFile(m_strFileName);
  349. }
  350. return bStatus ? S_OK : MapWin32ErrorCodeToHRes(GetLastError());
  351. }
  352. /*++
  353. Title:
  354. bSetEndOfFile
  355. Routine Description:
  356. If file handle is valid , set end of file
  357. Needed it for truncating the file in case of overwritting
  358. Called at the end of every successfull storing
  359. Arguments:
  360. None
  361. Return Value:
  362. TRUE if succeeded
  363. --*/
  364. BOOL
  365. TStream::
  366. bSetEndOfFile(
  367. VOID
  368. )
  369. {
  370. TStatusB bStatus;
  371. bStatus DBGCHK = (m_hFileHandle != INVALID_HANDLE_VALUE);
  372. if(bStatus)
  373. {
  374. bStatus DBGCHK = SetEndOfFile(m_hFileHandle);
  375. }
  376. return bStatus;
  377. }
  378. /*++
  379. Title:
  380. MapWin32ErrorCodeToHRes
  381. Routine Description:
  382. maps file error codes to HRESULT errors
  383. Arguments:
  384. Error value to convert
  385. Return Value:
  386. Converted error value to an HRESULT
  387. Last Error:
  388. --*/
  389. HRESULT
  390. TStream::
  391. MapWin32ErrorCodeToHRes(
  392. IN DWORD dwErrorCode
  393. )
  394. {
  395. return MAKE_HRESULT( SEVERITY_ERROR, FACILITY_STORAGE, dwErrorCode);
  396. }