00001
00034 #include "stdafx.h"
00035 #include "CFileMap.h"
00036
00037 namespace AxPipe {
00048 static void *
00049 MapUserView(HANDLE hMapping, longlong llOffset, size_t cbLen, void **ppvUserView, DWORD dwAccess) {
00050 static DWORD dwAllocationGranularity;
00051
00052 if (ppvUserView == NULL) {
00053 return NULL;
00054 }
00055
00056
00057 if (!dwAllocationGranularity) {
00058 SYSTEM_INFO SystemInfo;
00059 GetSystemInfo(&SystemInfo);
00060 dwAllocationGranularity = SystemInfo.dwAllocationGranularity;
00061 }
00062
00063 DWORD dwMisAlign = (DWORD)(llOffset % dwAllocationGranularity);
00064 cbLen += dwMisAlign;
00065 llOffset -= dwMisAlign;
00066
00067 void *vpView = MapViewOfFile(hMapping, dwAccess, (*(LARGE_INTEGER*)&llOffset).HighPart, (*(LARGE_INTEGER*)&llOffset).LowPart, cbLen);
00068 ASSAPI(vpView != NULL);
00069 *ppvUserView = (char *)vpView + dwMisAlign;
00070 return vpView;
00071 }
00079 CSegMap::CSegMap(void *pOwner, size_t cb, void *pv, void *pView, longlong llPos, bool fReadOnly) : CSeg(cb, pv, fReadOnly) {
00080 m_pView = pView;
00081 m_pOwner = pOwner;
00082 m_llPos = llPos;
00083 }
00084
00086 CSegMap::~CSegMap() {
00087 if (m_pView) {
00088 UnmapViewOfFile(m_pView);
00089 m_pView = NULL;
00090 }
00091 }
00092
00095 longlong
00096 CSegMap::GetPos() {
00097 return m_llPos;
00098 }
00099
00102 void *
00103 CSegMap::ClassId() {
00104 static int i;
00105 return &i;
00106 }
00107
00110 void *
00111 CSegMap::RTClassId() {
00112 return ClassId();
00113 }
00114
00118 bool
00119 CSegMap::IsOwner(void *pOwner) {
00120 return m_pOwner == pOwner;
00121 }
00122
00124 CSourceMemFile::CSourceMemFile() {
00125 m_szFileName = NULL;
00126 m_hFile = INVALID_HANDLE_VALUE;
00127 m_hMapping = NULL;
00128 }
00129
00132 HANDLE
00133 CSourceMemFile::GetHandle() {
00134 return m_hFile;
00135 }
00136
00141 CSourceMemFile *CSourceMemFile::Init(const _TCHAR *szFileName, size_t cbChunk) {
00142 m_cbChunk = cbChunk;
00143 size_t cbLen = lstrlen(szFileName);
00144 CopyMemory(m_szFileName = new _TCHAR[cbLen+1], szFileName, (cbLen + 1) * sizeof (_TCHAR));
00145 return this;
00146 }
00147
00153 bool CSourceMemFile::OutOpen() {
00154 m_hFile = CreateFile(m_szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
00155 if (m_hFile == INVALID_HANDLE_VALUE) {
00156 SetError(ERROR_CODE_GENERIC, _T("CSourceMemFile::CSourceMemFile failed to open %s"), m_szFileName);
00157 return false;
00158 }
00159 ((LARGE_INTEGER *)&m_cbFileSize)->LowPart =
00160 GetFileSize(m_hFile, (LPDWORD)&(((LARGE_INTEGER *)&m_cbFileSize)->HighPart));
00161 m_cbStreamPos = 0;
00162 m_hMapping = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
00163 if (!m_hMapping) {
00164 SetError(ERROR_CODE_GENERIC, _T("CSourceMemFile::CSourceMemFile failed to create file mapping for %s"), m_szFileName);
00165 return false;
00166 }
00167 return true;
00168 }
00169
00174 bool CSourceMemFile::OutClose(void) {
00175 if (m_hMapping) {
00176 if (!CloseHandle(m_hMapping)) {
00177 SetError(ERROR_CODE_GENERIC, _T("CSourceMemFile::Close failed to close mapping"));
00178 return true;
00179 }
00180 m_hMapping = NULL;
00181 }
00182 if (m_hFile != INVALID_HANDLE_VALUE) {
00183 if (!CloseHandle(m_hFile)) {
00184 SetError(ERROR_CODE_GENERIC, _T("CSourceMemFile::Close failed to close file"));
00185 return true;
00186 }
00187 m_hFile = INVALID_HANDLE_VALUE;
00188 }
00189 return true;
00190 }
00199 CSeg *CSourceMemFile::In() {
00200 if (m_cbStreamPos == m_cbFileSize) {
00201 return new CSeg;
00202 }
00203 size_t cbThisChunk = m_cbChunk;
00204 if (m_cbStreamPos + cbThisChunk > m_cbFileSize) {
00205 cbThisChunk = (size_t)(m_cbFileSize - m_cbStreamPos);
00206 }
00207
00208 void *pView, *pUserView;
00209 pView = MapUserView(m_hMapping, m_cbStreamPos, cbThisChunk, &pUserView, FILE_MAP_READ);
00210 CSeg *pSeg = new CSegMap(NULL, cbThisChunk, pUserView, pView, m_cbStreamPos, true);
00211 m_cbStreamPos += cbThisChunk;
00212 return pSeg;
00213 }
00214
00216 CSinkMemFile::CSinkMemFile() {
00217 m_szFileName = NULL;
00218 m_hFile = INVALID_HANDLE_VALUE;
00219 m_hMapping = NULL;
00220 InitializeCriticalSection(&m_CritSect);
00221 m_cbOutPos = m_cbInPos = 0;
00222 }
00223
00225 CSinkMemFile::~CSinkMemFile() {
00226 delete[] m_szFileName;
00227 DeleteCriticalSection(&m_CritSect);
00228 }
00229
00232 HANDLE
00233 CSinkMemFile::GetHandle() {
00234 return m_hFile;
00235 }
00236
00241 CSinkMemFile *
00242 CSinkMemFile::Init(const TCHAR *szFileName, size_t cbChunk) {
00243 m_cbChunk = cbChunk;
00244 size_t cbLen = lstrlen(szFileName);
00245 CopyMemory(m_szFileName = new _TCHAR[cbLen+1], szFileName, (cbLen + 1) * sizeof (_TCHAR));
00246 return this;
00247 }
00248
00253 bool
00254 CSinkMemFile::OutClose() {
00255 if (m_hMapping) {
00256 do {
00257 if (!CloseHandle(m_hMapping)) {
00258 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close failed to close mapping"));
00259 break;
00260 }
00261 m_hMapping = NULL;
00262 } while (false);
00263 }
00264 if (m_hFile != INVALID_HANDLE_VALUE) {
00265 do {
00266
00267
00268
00269 if (SetFilePointer(m_hFile, ((LARGE_INTEGER *)&m_cbOutPos)->LowPart, &((LARGE_INTEGER *)&m_cbOutPos)->HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
00270 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close set file pointer to end failed"));
00271 break;
00272 }
00273 if (!SetEndOfFile(m_hFile)) {
00274 DWORD dwErr = GetLastError();
00275 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close can't set end of file"));
00276 break;
00277 }
00278 if (!CloseHandle(m_hFile)) {
00279 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close failed to close file"));
00280 break;
00281 }
00282 m_hFile = INVALID_HANDLE_VALUE;
00283 } while (false);
00284 }
00285 return true;
00286 }
00300 CSeg *
00301 CSinkMemFile::OutGetSeg(size_t cb) {
00302 CSeg *pSeg;
00303
00304 EnterCriticalSection(&m_CritSect);
00305
00306 longlong cbPos = m_cbInPos > m_cbOutPos ? m_cbInPos : m_cbOutPos;
00307 if (m_hFile != INVALID_HANDLE_VALUE) {
00308 if (cbPos + cb > m_cbMappingSize) {
00309 m_cbMappingSize = cbPos + cb;
00310 if (m_hMapping) {
00311
00312
00313 if (!CloseHandle(m_hMapping)) {
00314 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::OutGetSeg failed to close mapping"));
00315 LeaveCriticalSection(&m_CritSect);
00316 return NULL;
00317 }
00318 m_hMapping = NULL;
00319 }
00320 }
00321 if (!m_hMapping) {
00322
00323 m_hMapping = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, ((LARGE_INTEGER *)&m_cbMappingSize)->HighPart, ((LARGE_INTEGER *)&m_cbMappingSize)->LowPart, NULL);
00324 if (!m_hMapping) {
00325 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::OutGetSeg failed to create file mapping"));
00326 LeaveCriticalSection(&m_CritSect);
00327 return NULL;
00328 }
00329 }
00330 void *pView, *pUserView;
00331 pView = MapUserView(m_hMapping, cbPos, cb, &pUserView, FILE_MAP_WRITE|FILE_MAP_READ);
00332 pSeg = new CSegMap(this, cb, pUserView, pView, cbPos);
00333 } else {
00334 pSeg = new CSeg(cb);
00335 }
00336 m_cbInPos = cbPos + cb;
00337 LeaveCriticalSection(&m_CritSect);
00338 return pSeg;
00339 }
00346 void
00347 CSinkMemFile::Out(CSeg *pSeg) {
00348 if (CSeg::IsSeg(pSeg)) {
00349
00350
00351
00352 EnterCriticalSection(&m_CritSect);
00353 if (pSeg->Len()) {
00354
00355 if ((pSeg->RTClassId() != CSegMap::ClassId()) || !((CSegMap *)pSeg)->IsOwner(this)) {
00356 CSeg *pOutSeg = OutGetSeg(pSeg->Len());
00357 if (!pOutSeg) {
00358 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [OutGetSeg() returned NULL]"));
00359 } else {
00360 CopyMemory(pOutSeg->PtrWr(), pSeg->PtrRd(), pSeg->Len());
00361 pOutSeg->Release();
00362 }
00363 } else {
00364
00365
00366
00367 CSegMap *pSegMap = (CSegMap *)pSeg;
00368 if (pSegMap->GetPos() > m_cbOutPos) {
00369 void *pView, *pUserView;
00370 pView = MapUserView(m_hMapping, m_cbOutPos, pSegMap->Len(), &pUserView, FILE_MAP_WRITE|FILE_MAP_READ);
00371 if (!pView) {
00372 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [MapUserView() returned NULL]"));
00373 } else {
00374 CopyMemory(pUserView, pSegMap->PtrRd(), pSegMap->Len());
00375 if (!(UnmapViewOfFile(pView))) {
00376 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [UnmapViewOfFile() failed]"));
00377 }
00378 }
00379 } else if (pSegMap->GetPos() < m_cbOutPos) {
00380
00381
00382
00383
00384 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [Output sequence error]"));
00385 }
00386
00387
00388 }
00389 }
00390 m_cbOutPos += pSeg->Len();
00391 pSeg->Release();
00392 LeaveCriticalSection(&m_CritSect);
00393 }
00394 }
00399 bool
00400 CSinkMemFile::OutOpen() {
00401
00402 m_hFile = CreateFile(m_szFileName, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
00403 if (m_hFile == INVALID_HANDLE_VALUE) {
00404 SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::CSinkMemFile failed to open %s"), m_szFileName);
00405 }
00406 ((LARGE_INTEGER *)&m_cbMappingSize)->LowPart = GetFileSize(m_hFile, (LPDWORD)&(((LARGE_INTEGER *)&m_cbMappingSize)->HighPart));
00407 m_cbOutPos = m_cbInPos = 0;
00408 return true;
00409 }
00410 };