//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: laylkb.cxx // // Contents: File ILockBytes implementation for layout storage // // Classes: // // Functions: // // History: 19-Feb-96 SusiA Created // //---------------------------------------------------------------------------- #include "layouthd.cxx" #pragma hdrstop #include "laylkb.hxx" #include #include class CSafeCriticalSection { public: inline CSafeCriticalSection(CRITICAL_SECTION *pcs); inline ~CSafeCriticalSection(); private: CRITICAL_SECTION *_pcs; }; inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs) { _pcs = pcs; EnterCriticalSection(_pcs); } inline CSafeCriticalSection::~CSafeCriticalSection() { LeaveCriticalSection(_pcs); #if DBG == 1 _pcs = NULL; #endif } #define TAKE_CS CSafeCriticalSection scs(&_cs); //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::CLayoutLockBytes, public // // Synopsis: Default constructor // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- CLayoutLockBytes::CLayoutLockBytes(void) { _cReferences = 1; _h = INVALID_HANDLE_VALUE; _hScript = INVALID_HANDLE_VALUE; _fLogging = FALSE; _cbSectorShift = 0; _atcScriptName[0] = TEXT('\0'); _awcName[0] = L'\0'; _fCSInitialized = FALSE; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::~CLayoutLockBytes, public // // Synopsis: Destructor // // Returns: Appropriate status code // // History: 20-Feb-96 SusiA Created // //---------------------------------------------------------------------------- CLayoutLockBytes::~CLayoutLockBytes() { if (_h != INVALID_HANDLE_VALUE) { CloseHandle(_h); _h = INVALID_HANDLE_VALUE; } if (_hScript != INVALID_HANDLE_VALUE) { CloseHandle(_hScript); _hScript = INVALID_HANDLE_VALUE; } if (_fCSInitialized) DeleteCriticalSection(&_cs); } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::Init, public // // Synopsis: Initialization function // // Arguments: // // Returns: Appropriate status code // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- SCODE CLayoutLockBytes::Init(OLECHAR const *pwcsName, DWORD grfMode) { SCODE sc = S_OK; BYTE abHeader[sizeof(CMSFHeaderData)]; ULONG cbRead; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Init:%p()\n", this)); if (pwcsName == NULL) return STG_E_INVALIDNAME; if (FALSE == _fCSInitialized) { __try { InitializeCriticalSection(&_cs); } __except( EXCEPTION_EXECUTE_HANDLER ) { return HRESULT_FROM_WIN32( GetExceptionCode() ); } _fCSInitialized = TRUE; } _grfMode = grfMode; #ifndef UNICODE TCHAR atcPath[MAX_PATH + 1]; UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; if (!WideCharToMultiByte( uCodePage, 0, pwcsName, -1, atcPath, MAX_PATH + 1, NULL, NULL)) { return STG_E_INVALIDNAME; } _h = CreateFileA(atcPath, GENERIC_READ | GENERIC_WRITE, //Read-write 0, // No sharing NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); #else _h = CreateFile(pwcsName, GENERIC_READ | GENERIC_WRITE, //Read-write 0, // No sharing NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); #endif if (_h == INVALID_HANDLE_VALUE) { layErr(Err, Win32ErrorToScode(GetLastError())); } layChk(StringCbCopyW(_awcName, sizeof(_awcName), pwcsName)); //Get the sector size boolChk(ReadFile(_h, abHeader, sizeof(CMSFHeaderData), &cbRead, NULL)); if (cbRead != sizeof(CMSFHeaderData)) { return STG_E_READFAULT; } _cbSectorShift = ((CMSFHeaderData *)abHeader)->_uSectorShift; if (((CMSFHeaderData*)abHeader)->_uDllVersion > rmjlarge) return STG_E_OLDDLL; layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Init\n")); Err: return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CLayoutLockBytes::QueryInterface, public // // Synopsis: Returns an object for the requested interface // // Arguments: [iid] - Interface ID // [ppvObj] - Object return // // Returns: Appropriate status code // // Modifies: [ppvObj] // // History: 26-Mar-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::QueryInterface(REFIID iid, void **ppvObj) { SCODE sc; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::QueryInterface(?, %p)\n", ppvObj)); layChk(ValidateOutPtrBuffer(ppvObj)); *ppvObj = NULL; sc = S_OK; if (IsEqualIID(iid, IID_IUnknown)) { *ppvObj = (IUnknown *)this; CLayoutLockBytes::AddRef(); } else if (IsEqualIID(iid, IID_ILockBytes)) { *ppvObj = (ILockBytes *)this; CLayoutLockBytes::AddRef(); } else { sc = E_NOINTERFACE; } layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::QueryInterface => %p\n", ppvObj)); Err: return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CLayoutLockBytes::AddRef, public // // Synopsis: Increments the ref count // // Returns: Appropriate status code // // History: 16-Mar-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP_(ULONG) CLayoutLockBytes::AddRef(void) { LONG lRet; layDebugOut((DEB_TRACE, "In CLayoutLockBytes::AddRef()\n")); lRet = InterlockedIncrement(&_cReferences); layDebugOut((DEB_TRACE, "Out CLayoutLockBytes::AddRef\n")); return lRet; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::Release, public // // History: 20-Feb-96 SusiA Created // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CLayoutLockBytes::Release(void) { LONG lRet; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Release:%p()\n", this)); lRet = InterlockedDecrement(&_cReferences); if (lRet == 0) { delete this; } layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Release\n")); return lRet; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::ReadAt, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::ReadAt(ULARGE_INTEGER ulOffset, VOID HUGEP *pv, ULONG cb, ULONG *pcbRead) { CSafeCriticalSection scs(&_cs); SCODE sc = S_OK; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::ReadAt:%p()\n", this)); ULONG ulLow = ulOffset.LowPart; LONG lHigh = (LONG)ulOffset.HighPart; if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData))) { if (_hScript == INVALID_HANDLE_VALUE) { return STG_E_INVALIDHANDLE; } ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart - ((ULONGLONG)1 << _cbSectorShift)) >> _cbSectorShift); ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) - ((ULONGLONG)1 << _cbSectorShift)) >> _cbSectorShift); ULONG ulSect; ULONG cbScriptWritten; for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++) { layAssert(_hScript !=INVALID_HANDLE_VALUE); boolChk(WriteFile(_hScript, (VOID *)&ulSect, sizeof(ULONG), &cbScriptWritten, NULL)); if (cbScriptWritten != sizeof(ULONG)) { return STG_E_WRITEFAULT; } } } negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN)); boolChk(ReadFile(_h, pv, cb, pcbRead, NULL)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::ReadAt\n")); Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::WriteAt, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::WriteAt(ULARGE_INTEGER ulOffset, VOID const HUGEP *pv, ULONG cb, ULONG *pcbWritten) { CSafeCriticalSection scs(&_cs); SCODE sc = S_OK; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::WriteAt:%p()\n", this)); ULONG ulLow = ulOffset.LowPart; LONG lHigh = (LONG)ulOffset.HighPart; if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData))) { if (_hScript == INVALID_HANDLE_VALUE) { return STG_E_INVALIDHANDLE; } ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart - ((ULONGLONG)1 << _cbSectorShift)) >> _cbSectorShift); ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) - ((ULONGLONG)1 << _cbSectorShift)) >> _cbSectorShift); ULONG ulSect; ULONG cbScriptWritten; for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++) { boolChk(WriteFile(_hScript, (VOID *)&ulSect, sizeof(ULONG), &cbScriptWritten, NULL)); if (cbScriptWritten != sizeof(ULONG)) { return STG_E_WRITEFAULT; } } } negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN)); boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::WriteAt\n")); Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::Flush, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::Flush(void) { layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Flush:%p()\n", this)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Flush\n")); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::SetSize, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::SetSize(ULARGE_INTEGER cb) { CSafeCriticalSection scs(&_cs); SCODE sc = S_OK; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::SetSize:%p()\n", this)); LONG lHigh = (LONG)cb.HighPart; ULONG ulLow = cb.LowPart; negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN)); boolChk(SetEndOfFile(_h)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::SetSize\n")); Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::LockRegion, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { CSafeCriticalSection scs(&_cs); SCODE sc = S_OK; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::LockRegion:%p()\n", this)); if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE) { return STG_E_INVALIDFUNCTION; } boolChk(LockFile(_h, libOffset.LowPart, libOffset.HighPart, cb.LowPart, cb.HighPart)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::LockRegion\n")); Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::UnlockRegion, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { CSafeCriticalSection scs(&_cs); SCODE sc = S_OK; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::UnlockRegion:%p()\n", this)); if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE) { return STG_E_INVALIDFUNCTION; } boolChk(UnlockFile(_h, libOffset.LowPart, libOffset.HighPart, cb.LowPart, cb.HighPart)); layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::UnlockRegion\n")); Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::Stat, public // // Synopsis: // // Arguments: // // Returns: Appropriate status code // // Modifies: // // History: 20-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CLayoutLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag) { CSafeCriticalSection scs(&_cs); SCODE sc; layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Stat:%p()\n", this)); negChk(pstatstg->cbSize.LowPart = GetFileSize(_h, &pstatstg->cbSize.HighPart)); boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime, &pstatstg->mtime)); pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE; pstatstg->type = STGTY_LOCKBYTES; pstatstg->grfMode = _grfMode; pstatstg->pwcsName = NULL; if ((grfStatFlag & STATFLAG_NONAME) == 0) { pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc( (lstrlenW(_awcName) + 1) * sizeof(OLECHAR)); if (pstatstg->pwcsName == NULL) return STG_E_INSUFFICIENTMEMORY; StringCchCopyW (pstatstg->pwcsName, lstrlenW(_awcName)+1, _awcName); } sc = S_OK; layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Stat\n")); return NOERROR; Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::StartLogging, public // // Returns: Appropriate status code // // Modifies: _fLogging // // History: 24-Feb-96 SusiA Created // // Notes: // //---------------------------------------------------------------------------- SCODE CLayoutLockBytes::StartLogging(void) { CSafeCriticalSection scs(&_cs); OLECHAR acTempPathName[MAX_PATH + 1]; SCODE sc = S_OK; if (_fLogging) { return STG_E_INUSE; //logging already started! } if (_atcScriptName[0] != TEXT('\0')) { LONG dwDistanceToMoveHigh = 0; //Script has already been started. Need to reopen it and seek // to the end. #ifndef UNICODE _hScript = CreateFileA #else _hScript = CreateFile #endif (_atcScriptName, GENERIC_WRITE, //Read-write 0, // No sharing NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); if (_hScript == INVALID_HANDLE_VALUE) { return LAST_STG_SCODE; } negChk(SetFilePointer(_hScript, 0, &dwDistanceToMoveHigh, FILE_END)); } else { TCHAR atcPath[MAX_PATH + 1]; //Generate the script name, then create it. UINT ui = GetTempPath(MAX_PATH, atcPath); if (0 == ui) { layErr(Err, Win32ErrorToScode(GetLastError())); } else if (ui > MAX_PATH) { layErr(Err, STG_E_PATHNOTFOUND); } boolChk(GetTempFileName(atcPath, TEXT("SCR"), 0, _atcScriptName)); //GetTempFileName actually creates the file, so we open with // OPEN_EXISTING #ifndef UNICODE _hScript = CreateFileA #else _hScript = CreateFile #endif (_atcScriptName, GENERIC_READ | GENERIC_WRITE, //Read-write 0, // No sharing NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); if (_hScript == INVALID_HANDLE_VALUE) { return LAST_STG_SCODE; } } _fLogging = TRUE; Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CLayoutLockBytes::StopLogging, public // // Returns: Appropriate status code // // Modifies: _fLogging // // History: 24-Feb-96 SusiA Created // // Notes: // //----------------------------------------------------------------------------- SCODE CLayoutLockBytes::StopLogging(void) { SCODE sc = S_OK; CSafeCriticalSection scs(&_cs); if (!_fLogging) { return STG_E_UNKNOWN; } boolChk(CloseHandle(_hScript)); _hScript = INVALID_HANDLE_VALUE; _fLogging = FALSE; Err: return sc; }