From b2bcaae1c2a378c36c84d9f598926521b4dade3f Mon Sep 17 00:00:00 2001 From: "Ivan.Shulga" Date: Wed, 20 Nov 2013 09:10:24 +0000 Subject: [PATCH] git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@52258 954022d7-b5bf-4e40-9824-e11837661b57 --- Common/ATLDefine.h | 231 +++++++++++++++++++++++++++++++++++++++ Common/FileWriter.h | 258 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 489 insertions(+) create mode 100644 Common/ATLDefine.h create mode 100644 Common/FileWriter.h diff --git a/Common/ATLDefine.h b/Common/ATLDefine.h new file mode 100644 index 0000000000..5f9bd30a0e --- /dev/null +++ b/Common/ATLDefine.h @@ -0,0 +1,231 @@ +#ifndef ATLDEFINE_H_DEFINE +#define ATLDEFINE_H_DEFINE + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +//LINK_PROPERTY macros +#define LINK_PROPERTY_LONG(propName, memberName)\ + STDMETHOD(get_##propName##)(long* pVal)\ + {\ + *pVal = ##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(long newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_SHORT(propName, memberName)\ + STDMETHOD(get_##propName##)(SHORT* pVal)\ + {\ + *pVal = ##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(SHORT newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_BOOL(propName, memberName)\ + STDMETHOD(get_##propName##)(VARIANT_BOOL* pVal)\ + {\ + *pVal = ##memberName## ? VARIANT_TRUE : VARIANT_FALSE;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(VARIANT_BOOL newVal)\ + {\ + ##memberName## = (VARIANT_FALSE!=newVal);\ + return S_OK;\ + } +#define LINK_PROPERTY_VARIANT_BOOL(propName, memberName)\ + STDMETHOD(get_##propName##)(VARIANT_BOOL* pVal)\ + {\ + *pVal = ##memberName## ? VARIANT_TRUE : VARIANT_FALSE;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(VARIANT_BOOL newVal)\ + {\ + ##memberName## = (VARIANT_FALSE!=newVal)?VARIANT_TRUE : VARIANT_FALSE;\ + return S_OK;\ + } +#define LINK_PROPERTY_ULONG(propName, memberName)\ + STDMETHOD(get_##propName##)(ULONG* pVal)\ + {\ + *pVal = ##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(ULONG newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_USHORT(propName, memberName)\ + STDMETHOD(get_##propName##)(USHORT* pVal)\ + {\ + *pVal = ##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(USHORT newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_BSTR(propName, memberName)\ + STDMETHOD(get_##propName##)(BSTR* pVal)\ + {\ + *pVal = ##memberName##.AllocSysString();\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(BSTR newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_DOUBLE(propName, memberName)\ + STDMETHOD(get_##propName##)(double* pVal)\ + {\ + *pVal = ##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(double newVal)\ + {\ + ##memberName## = newVal;\ + return S_OK;\ + } + +#define LINK_PROPERTY_SAFEARRAY(propName, memberName)\ + STDMETHOD(get_##propName##)(LPSAFEARRAY* pVal)\ + {\ + *pVal = NULL;\ + if (NULL!=##memberName##)\ + {\ + SAFEARRAYBOUND rgsaBound[1];\ + rgsaBound[0].lLbound = 0;\ + rgsaBound[0].cElements = ##memberName##->rgsabound[0].cElements;\ + *pVal = SafeArrayCreate(VT_UI1, 1, rgsaBound);\ + memcpy((*pVal)->pvData, ##memberName##->pvData, ##memberName##->rgsabound[0].cElements);\ + }\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(LPSAFEARRAY newVal)\ + {\ + RELEASEARRAY(##memberName##);\ + if (NULL!=newVal)\ + {\ + SAFEARRAYBOUND rgsaBound[1];\ + rgsaBound[0].lLbound = 0;\ + rgsaBound[0].cElements = newVal->rgsabound[0].cElements;\ + ##memberName## = SafeArrayCreate(VT_UI1, 1, rgsaBound);\ + if (NULL==##memberName##)\ + return S_FALSE;\ + memcpy(##memberName##->pvData, newVal->pvData, newVal->rgsabound->cElements);\ + }\ + return S_OK;\ + } + +#define LINK_PROPERTY_ARRAY_LONG(propName, arrayName, memberName)\ + STDMETHOD(get_##propName##)(long Index, long* pVal)\ + {\ + if ((0>Index)||(Index>=(long)##arrayName##.GetCount()))\ + return S_OK;\ + *pVal = ##arrayName##[Index].##memberName##;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(long Index, long newVal)\ + {\ + if ((0>Index)||(Index>=(long)##arrayName##.GetCount()))\ + return S_OK;\ + ##arrayName##[Index].##memberName## = newVal;\ + return S_OK;\ + } +#define LINK_PROPERTY_ARRAY_BOOL(propName, arrayName, memberName)\ + STDMETHOD(get_##propName##)(long Index, VARIANT_BOOL* pVal)\ + {\ + if ((0>Index)||(Index>=(long)##arrayName##.GetCount()))\ + return S_OK;\ + *pVal = ##arrayName##[Index].##memberName## ? VARIANT_TRUE : VARIANT_FALSE;\ + return S_OK;\ + }\ + STDMETHOD(put_##propName##)(long Index, VARIANT_BOOL newVal)\ + {\ + if ((0>Index)||(Index>=(long)##arrayName##.GetCount()))\ + return S_OK;\ + ##arrayName##[Index].##memberName## = (VARIANT_FALSE!=newVal);\ + return S_OK;\ + } + +// memory release macros +#define ADDREFINTERFACE(pinterface)\ +{\ + if (pinterface!=NULL)\ + {\ + pinterface->AddRef();\ + }\ +} +#define RELEASEINTERFACE(pinterface)\ +{\ + if (pinterface!=NULL)\ + {\ + pinterface->Release();\ + pinterface=NULL;\ + }\ +} +#define RELEASEMEM(pobject)\ +{\ + if (pobject!=NULL)\ + {\ + free(pobject);\ + pobject=NULL;\ + }\ +} +#define RELEASEOBJECT(pobject)\ +{\ + if (pobject!=NULL)\ + {\ + delete pobject;\ + pobject=NULL;\ + }\ +} +#define RELEASEARRAYOBJECTS(pobject)\ +{\ + if (pobject!=NULL)\ + {\ + delete []pobject;\ + pobject=NULL;\ + }\ +} +#define RELEASEHEAP(pmem)\ +{\ + if (pmem!=NULL)\ + {\ + HeapFree(GetProcessHeap(), 0, pmem);\ + pmem=NULL;\ + }\ +} +#define RELEASEARRAY(parray)\ +{\ + if (parray!=NULL)\ + {\ + SafeArrayDestroy(parray);\ + parray=NULL;\ + }\ +} +#define RELEASESYSSTRING(pstring)\ +{\ + if (pstring!=NULL)\ + {\ + SysFreeString(pstring);\ + pstring=NULL;\ + }\ +} +#define RELEASEHANDLE(phandle)\ +{\ + if (phandle!=NULL)\ + {\ + CloseHandle(phandle);\ + phandle=NULL;\ + }\ +} +#endif //ATLDEFINE \ No newline at end of file diff --git a/Common/FileWriter.h b/Common/FileWriter.h new file mode 100644 index 0000000000..fd526eb5a1 --- /dev/null +++ b/Common/FileWriter.h @@ -0,0 +1,258 @@ +#pragma once + +namespace NFileWriter +{ + //------------------------------------------------------------------------------------------------------ + // CBufferedFileWriter + //------------------------------------------------------------------------------------------------------ + // Абстрактный класс, который содержит в себе объявления функций + //------------------------------------------------------------------------------------------------------ + + class CFileWriter + { + public : + + // Принимает данные на запись + virtual VOID Write ( LPBYTE lpData, LONG64 lDataLength ) = 0; + // Флаш ( дописываем все данные ) + virtual VOID Flush () = 0; + // Сик на указанную позицию по файлу + virtual VOID Seek ( LONG64 lPosition, DWORD dwFrom = FILE_CURRENT ) = 0; + // Текущая позиция + virtual VOID GetPosition(ULONGLONG& nPos) = 0; + // Размер записанного файла + virtual VOID GetSize(ULONGLONG& nLen) = 0; + + public : + + // Конструктор + CFileWriter () + { + } + // Виртуальный деструктор + virtual ~CFileWriter () + { + } + }; + + //------------------------------------------------------------------------------------------------------ + // CBufferedFileWriter + //------------------------------------------------------------------------------------------------------ + // Класс, который занимается записью файла на диск + //------------------------------------------------------------------------------------------------------ + + class CBufferedFileWriter : public CFileWriter + { + private : + + HANDLE m_hFile; // Хендл на файл, в который идет запись + + LONG64 m_lBufferSize; // Размер буффера + + LPBYTE m_lpBuffer; // Сам буффер + + LONG64 m_lWritePointer; // Позиция для записи данных в буффер + + public : + + // Конструктор ( от имени файла, сам контрол открывает файл ) + CBufferedFileWriter ( TCHAR *lpszFile, LONG64 lBufferSize = 10 * 1024 * 1024 ) : CFileWriter () + { + // Создаем хендл на файл, в который будет осуществляться запись, и инициализируем хендл, который следует закрыть + m_hFile = CreateFile (lpszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + + // Если не получилось открыть файл + if ( INVALID_HANDLE_VALUE == m_hFile ) + { + // Выдаем исключение + throw 1; + } + + // Копируем данные + m_lBufferSize = lBufferSize; + + // Обнуляем переменные + m_lWritePointer = 0; + + // Выделяем буфер. + m_lpBuffer = ( LPBYTE ) ::HeapAlloc ( GetProcessHeap (), HEAP_ZERO_MEMORY, (size_t) m_lBufferSize ); + + // Если буффер не выделился, возвращаем Exception + if ( !m_lpBuffer ) + { + // Выдаем исключение + throw 1; + } + + // Все отлично!!! + } + + // Деструктор + virtual ~CBufferedFileWriter () + { + // Если нужно закрыть файл, закрываем его + if ( m_hFile && m_hFile != INVALID_HANDLE_VALUE ) + { + // Дописываем сначала все данные оставшиеся, а затем удаляем + try + { + // Это на случай, если писать больше не можем, но файл-то удалить нужно + Flush (); + } + catch ( ... ) + { + } + CloseHandle ( m_hFile ); + m_hFile = NULL; + } + + // Удаляем буффер + if ( m_lpBuffer ) + { + ::HeapFree ( GetProcessHeap (), 0, m_lpBuffer ); + m_lpBuffer = NULL; + } + } + // Принимает данные на запись + virtual VOID Write ( LPBYTE lpData, LONG64 lDataLength ) + { + // Пока размер данных не исчерпан + while ( 0 < lDataLength ) + { + // Размер свободной памяти в буффере + LONG64 lBufferFreeLength = 0; + + // Цикл, пока не появится свободное место для записи + while ( 0 >= ( lBufferFreeLength = m_lBufferSize - m_lWritePointer ) ) + { + // Пишем данные, если не получилось, то генерируем исключение + if ( FALSE == WriteBuffer ( m_lBufferSize ) ) + throw 1; + } + + // Проверяем достаточно ли места, чтобы записать весь пришедший буфер в память + if ( lBufferFreeLength > lDataLength ) + lBufferFreeLength = lDataLength; + + // Копируем данные в буффер + memcpy ( m_lpBuffer + m_lWritePointer, lpData, (size_t) lBufferFreeLength); + + // Уменьшаем размер данных ровно на столько, сколько записали в буффер + lDataLength -= lBufferFreeLength; + // Сдвигаем указатель на пришедшие данные + lpData = lpData + lBufferFreeLength; + // Сдвигаем позицию для записи данных в буффер + m_lWritePointer += lBufferFreeLength; + } + } + // Флаш ( дописываем все данные ) + virtual VOID Flush () + { + // Пишем все данные, которые есть + if ( 0 < m_lWritePointer ) + { + // Если пришла ошибка, то генерируем исключение + if ( FALSE == WriteBuffer ( m_lWritePointer ) ) + throw 1; + } + } + // Сик на указанную позицию по файлу + virtual VOID Seek ( LONG64 lPosition, DWORD dwFrom = FILE_CURRENT ) + { + + // Допишем сначала все данные + Flush (); + + // Делаем сик по файлу + LARGE_INTEGER liOffset; + liOffset.QuadPart = lPosition; + DWORD nNewPos = ::SetFilePointer(m_hFile, liOffset.LowPart, &liOffset.HighPart, dwFrom); + + if (nNewPos == INVALID_SET_FILE_POINTER) + { + HRESULT hr; + + hr = AtlHresultFromLastError(); + if (FAILED(hr)) + throw 1; + } + + } + // Текущая позиция + virtual VOID GetPosition(ULONGLONG& nPos) + { + nPos=0; + if(m_hFile == NULL)return; + + LARGE_INTEGER liOffset; + liOffset.QuadPart = 0; + liOffset.LowPart = ::SetFilePointer(m_hFile, 0, &liOffset.HighPart, FILE_CURRENT); + if (liOffset.LowPart == INVALID_SET_FILE_POINTER) + { + HRESULT hr; + + hr = AtlHresultFromLastError(); + if (FAILED(hr)) + throw 1; + } + nPos = liOffset.QuadPart + m_lWritePointer; + } + // Размер записанного файла + virtual void GetSize(ULONGLONG& nLen) + { + nLen=0; + if(m_hFile == NULL)return; + + LARGE_INTEGER liOffset; + ULARGE_INTEGER liFileSize; + + liOffset.QuadPart = 0; + liOffset.LowPart = ::SetFilePointer(m_hFile, 0, &liOffset.HighPart, FILE_CURRENT); + + liFileSize.LowPart = ::GetFileSize(m_hFile, &liFileSize.HighPart); + + if (liFileSize.LowPart == INVALID_FILE_SIZE || liOffset.LowPart == INVALID_SET_FILE_POINTER) + { + HRESULT hr; + + hr = AtlHresultFromLastError(); + if (FAILED(hr)) + throw 1; + } + + nLen = liFileSize.QuadPart; + + if (liFileSize.QuadPart==liOffset.QuadPart) //находимся в конце файла то есть учитываем буфер + { + nLen += m_lWritePointer; + } + } + private : + + // Сама запись на диск + BOOL WriteBuffer ( LONG64 lSize ) + { + // Проверка + if ( INVALID_HANDLE_VALUE == m_hFile || 0 == lSize ) + return FALSE; + + // Сколько байт записалось на диск + DWORD dwBytesWrite = 0; + + // Пишем на диск + if ( !WriteFile ( m_hFile, m_lpBuffer, ( DWORD ) lSize, &dwBytesWrite, NULL ) ) + { + // Если что-то произошло не так, возвращаем FALSE + return FALSE; + } + + // Проверка, если записалось меньше, то это ошибка + if ( ( LONG64 ) dwBytesWrite != lSize ) + return FALSE; + + // Сбрасываем в 0 указатель на позицию данных в буффере + m_lWritePointer = 0; + return TRUE; + } + }; +} \ No newline at end of file