#include "stdafx.h"
#ifdef __linux__
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#endif
#include <stdio.h>
#include <wchar.h>
#include "AddInNative.h"
#include <string>
#define TIME_LEN 34
#define BASE_ERRNO 7
static wchar_t *g_PropNames[] = {L"IsInited", L"Version", L"MaxTimeBetweenClicks", L"BufferSize", L"Prefix", L"Suffix"};
static wchar_t *g_MethodNames[] = {L"Init", L"Deinit", L"GetBarcode"};
static wchar_t *g_PropNamesRu[] = {L"Инициализирован", L"Версия", L"МаксВремяМеждуНажатиями", L"РазмерБуфера", L"Префикс", L"Суффикс"};
static wchar_t *g_MethodNamesRu[] = {L"Инициализация", L"Деинициализация", L"ПолучитьШтрихкод"};
static const wchar_t g_kClassNames[] = L"Scaner";
static IAddInDefBase *pAsyncEvent = NULL;
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len = 0);
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len = 0);
uint32_t getLenShortWcharStr(const WCHAR_T* Source);
/*
HHOOK hHook;
HWND hWnd;
unsigned long barcode_time = 0;
wchar_t barcode_string[250];
int barcode_current = 0;
*/
/*
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
MSG *msg = (MSG *)lParam;
if (code == HC_ACTION && wParam == PM_REMOVE)
{
if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
{
if ((msg->time - barcode_time) < 30 || !barcode_time)
{
barcode_string[barcode_current] = msg->wParam;
barcode_time = msg->time;
if (msg->wParam == 0x000D)
{
barcode_string[barcode_current] = 0x0000;
barcode_current = 0;
barcode_time = 0;
pAsyncEvent->ExternalEvent(L"Scaner", L"KeyBd", barcode_string);
} else barcode_current++;
} else
{
barcode_current = 0;
barcode_time = 0;
}
msg->message = 0x00;
}
}
return CallNextHookEx(pAsyncEvent-> hHook, code, wParam, lParam);
}
*/
/* ThreadProc && GetMsgProc */
#include "bcbuffer.h"
CircularBuffer bcbuf;
CAddInNative *driver;
DWORD WINAPI ThreadProc(CONST LPVOID lpParam)
{
driver->m_boolThreadExit = false;
while (!driver->m_boolThreadExit)
{
pAsyncEvent->ExternalEvent(L"Scaner", L"Thread", L"");
Sleep(5000);
}
driver->m_boolThreadExit = false;
return 0;
}
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
MSG *msg = (MSG *)lParam;
if (code == HC_ACTION && wParam == PM_REMOVE)
{
if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
{
wchar_t buf[64];
wsprintf(buf, L"%x - %x", msg->wParam, msg->time);
pAsyncEvent->ExternalEvent(L"Scaner", L"KeyBd", buf);
msg->message = 0;
}
}
return CallNextHookEx((HHOOK)driver->m_hhookKeyBDHook, code, wParam, lParam);
}
//---------------------------------------------------------------------------//
long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
if(!*pInterface)
{
*pInterface = new CAddInNative;
driver = (CAddInNative *)*pInterface;
return (long)*pInterface;
}
return 0;
}
//---------------------------------------------------------------------------//
long DestroyObject(IComponentBase** pIntf)
{
if(!*pIntf)
return -1;
delete *pIntf;
*pIntf = 0;
return 0;
}
//---------------------------------------------------------------------------//
const WCHAR_T* GetClassNames()
{
static WCHAR_T* names = 0;
if (!names)
::convToShortWchar(&names, g_kClassNames);
return names;
}
// CAddInNative
//---------------------------------------------------------------------------//
CAddInNative::CAddInNative()
{
m_iMemory = 0;
m_iConnect = 0;
m_boolInited = false;
m_longMaxTimeBetweenClicks = 30;
m_longBufferSize = 5000;
wcscpy(m_wstrVersion, L"1.0");
wcscpy(m_wstrPrefix, L"");
wcscpy(m_wstrSuffix, L"");
m_longTypeBarcode = 0;
wcscpy(m_wstrBarcode, L"123");
}
//---------------------------------------------------------------------------//
CAddInNative::~CAddInNative()
{
}
//---------------------------------------------------------------------------//
bool CAddInNative::Init(void* pConnection)
{
m_iConnect = (IAddInDefBase*)pConnection;
pAsyncEvent = m_iConnect;
return m_iConnect != NULL;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetInfo()
{
// Component should put supported component technology version
// This component supports 2.0 version
return 2000;
}
//---------------------------------------------------------------------------//
void CAddInNative::Done()
{
}
/////////////////////////////////////////////////////////////////////////////
// ILanguageExtenderBase
//---------------------------------------------------------------------------//
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName)
{
wchar_t *wsExtension = L"AddInNativeExtension";
int iActualSize = ::wcslen(wsExtension) + 1;
WCHAR_T* dest = 0;
if (m_iMemory)
{
if(m_iMemory->AllocMemory((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(wsExtensionName, wsExtension, iActualSize);
return true;
}
return false;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNProps()
{
// You may delete next lines and add your own implementation code here
return ePropLast;
}
//---------------------------------------------------------------------------//
long CAddInNative::FindProp(const WCHAR_T* wsPropName)
{
long plPropNum = -1;
wchar_t* propName = 0;
::convFromShortWchar(&propName, wsPropName);
plPropNum = findName(g_PropNames, propName, ePropLast);
if (plPropNum == -1)
plPropNum = findName(g_PropNamesRu, propName, ePropLast);
delete[] propName;
return plPropNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CAddInNative::GetPropName(long lPropNum, long lPropAlias)
{
if (lPropNum >= ePropLast)
return NULL;
wchar_t *wsCurrentName = NULL;
WCHAR_T *wsPropName = NULL;
int iActualSize = 0;
switch(lPropAlias)
{
case 0: // First language
wsCurrentName = g_PropNames[lPropNum];
break;
case 1: // Second language
wsCurrentName = g_PropNamesRu[lPropNum];
break;
default:
return 0;
}
iActualSize = wcslen(wsCurrentName)+1;
if (m_iMemory && wsCurrentName)
{
if (m_iMemory->AllocMemory((void**)&wsPropName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsPropName, wsCurrentName, iActualSize);
}
return wsPropName;
}
//---------------------------------------------------------------------------//
bool CAddInNative::GetPropVal(const long lPropNum, tVariant* pvarPropVal)
{
switch(lPropNum)
{
case ePropIsInited:
TV_VT(pvarPropVal) = VTYPE_BOOL;
TV_BOOL(pvarPropVal) = m_boolInited;
break;
case ePropVersion:
TV_VT(pvarPropVal) = VTYPE_PWSTR;
pvarPropVal->pwstrVal = m_wstrVersion;
pvarPropVal->wstrLen = wcslen(m_wstrVersion);
break;
case ePropMaxTimeBetweenClicks:
TV_VT(pvarPropVal) = VTYPE_I4;
TV_I4(pvarPropVal) = m_longMaxTimeBetweenClicks;
break;
case ePropBufferSize:
TV_VT(pvarPropVal) = VTYPE_I4;
TV_I4(pvarPropVal) = m_longBufferSize;
break;
case ePropPrefix:
TV_VT(pvarPropVal) = VTYPE_PWSTR;
pvarPropVal->pwstrVal = m_wstrPrefix;
pvarPropVal->wstrLen = wcslen(m_wstrPrefix);
break;
case ePropSuffix:
TV_VT(pvarPropVal) = VTYPE_PWSTR;
pvarPropVal->pwstrVal = m_wstrSuffix;
pvarPropVal->wstrLen = wcslen(m_wstrSuffix);
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::SetPropVal(const long lPropNum, tVariant *varPropVal)
{
switch(lPropNum)
{
case ePropMaxTimeBetweenClicks:
if (TV_VT(varPropVal) != VTYPE_I4)
return false;
m_longMaxTimeBetweenClicks = TV_I4(varPropVal);
break;
case ePropPrefix:
if (TV_VT(varPropVal) != VTYPE_PWSTR)
return false;
wcscpy(m_wstrPrefix, varPropVal->pwstrVal);
break;
case ePropSuffix:
if (TV_VT(varPropVal) != VTYPE_PWSTR)
return false;
wcscpy(m_wstrSuffix, varPropVal->pwstrVal);
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::IsPropReadable(const long lPropNum)
{
switch(lPropNum)
{
case ePropIsInited:
case ePropVersion:
case ePropMaxTimeBetweenClicks:
case ePropBufferSize:
case ePropPrefix:
case ePropSuffix:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::IsPropWritable(const long lPropNum)
{
switch(lPropNum)
{
case ePropMaxTimeBetweenClicks:
case ePropPrefix:
case ePropSuffix:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNMethods()
{
return eMethLast;
}
//---------------------------------------------------------------------------//
long CAddInNative::FindMethod(const WCHAR_T* wsMethodName)
{
long plMethodNum = -1;
wchar_t* name = 0;
::convFromShortWchar(&name, wsMethodName);
plMethodNum = findName(g_MethodNames, name, eMethLast);
if (plMethodNum == -1)
plMethodNum = findName(g_MethodNamesRu, name, eMethLast);
return plMethodNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CAddInNative::GetMethodName(const long lMethodNum, const long lMethodAlias)
{
if (lMethodNum >= eMethLast)
return NULL;
wchar_t *wsCurrentName = NULL;
WCHAR_T *wsMethodName = NULL;
int iActualSize = 0;
switch(lMethodAlias)
{
case 0: // First language
wsCurrentName = g_MethodNames[lMethodNum];
break;
case 1: // Second language
wsCurrentName = g_MethodNamesRu[lMethodNum];
break;
default:
return 0;
}
iActualSize = wcslen(wsCurrentName)+1;
if (m_iMemory && wsCurrentName)
{
if(m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize);
}
return wsMethodName;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNParams(const long lMethodNum)
{
switch(lMethodNum)
{
case eMethInit:
return 4;
case eMethDeinit:
return 0;
case eMethGetBarcode:
return 2;
default:
return 0;
}
return 0;
}
//---------------------------------------------------------------------------//
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum,
tVariant *pvarParamDefValue)
{
TV_VT(pvarParamDefValue)= VTYPE_EMPTY;
switch(lMethodNum)
{
case eMethInit:
{
if (lParamNum == 0)
{
TV_VT(pvarParamDefValue) = VTYPE_I4;
TV_I4(pvarParamDefValue) = 0;
} else if (lParamNum == 1)
{
TV_VT(pvarParamDefValue) = VTYPE_I4;
TV_I4(pvarParamDefValue) = 0;
} else if (lParamNum == 2)
{
TV_VT(pvarParamDefValue) = VTYPE_PWSTR;
pvarParamDefValue->wstrLen = 0;
} else if (lParamNum == 3)
{
TV_VT(pvarParamDefValue) = VTYPE_PWSTR;
pvarParamDefValue->wstrLen = 0;
}
return true;
}
case eMethDeinit:
break;
case eMethGetBarcode:
{
if (lParamNum == 0)
{
TV_VT(pvarParamDefValue) = VTYPE_I4;
TV_I4(pvarParamDefValue) = 0;
} else if (lParamNum == 1)
{
TV_VT(pvarParamDefValue) = VTYPE_PWSTR;
pvarParamDefValue->pwstrVal = (wchar_t *)&m_wstrBarcode;
pvarParamDefValue->wstrLen = 0;
}
return true;
}
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::HasRetVal(const long lMethodNum)
{
switch(lMethodNum)
{
case eMethInit:
case eMethDeinit:
case eMethGetBarcode:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray)
{
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{
bool ret = false;
switch(lMethodNum)
{
case eMethInit:
{
TV_VT(pvarRetValue) = VTYPE_BOOL;
if (!m_boolInited && lSizeArray == 4 && TV_VT(&paParams[0]) == VTYPE_I4 && TV_VT(&paParams[1]) == VTYPE_I4 && TV_VT(&paParams[2]) == VTYPE_PWSTR && TV_VT(&paParams[3]) == VTYPE_PWSTR)
{
m_longMaxTimeBetweenClicks = TV_I4(&paParams[0]);
m_longBufferSize = TV_I4(&paParams[1]);
if (paParams[2].pwstrVal)
wcscpy(m_wstrPrefix, paParams[2].pwstrVal);
if (paParams[3].pwstrVal)
wcscpy(m_wstrSuffix, paParams[3].pwstrVal);
if (!cbInit(&bcbuf, m_longBufferSize))
{
TV_BOOL(pvarRetValue) = false;
return true;
}
if (!(m_hhookKeyBDHook = (unsigned long)SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId())))
{
TV_BOOL(pvarRetValue) = false;
return true;
}
if (!(m_handleThread = (unsigned long)CreateThread(NULL, 0, &ThreadProc, NULL, 0, NULL)))
{
UnhookWindowsHookEx((HHOOK)m_hhookKeyBDHook);
TV_BOOL(pvarRetValue) = false;
return true;
}
m_boolInited = true;
TV_BOOL(pvarRetValue) = true;
} else
{
TV_BOOL(pvarRetValue) = false;
}
return true;
}
case eMethDeinit:
{
TV_VT(pvarRetValue) = VTYPE_BOOL;
if (m_boolInited)
{
m_boolThreadExit = true;
while(m_boolThreadExit);
cbFree(&bcbuf);
if (UnhookWindowsHookEx((HHOOK)m_hhookKeyBDHook))
{
m_boolInited = false;
TV_BOOL(pvarRetValue) = true;
} else
{
TV_BOOL(pvarRetValue) = false;
}
TV_BOOL(pvarRetValue) = true;
} else
{
TV_BOOL(pvarRetValue) = false;
}
return true;
}
case eMethGetBarcode:
{
TV_VT(pvarRetValue) = VTYPE_BOOL;
if (m_boolInited && lSizeArray == 2)
{
TV_VT(&paParams[0]) = VTYPE_I4;
TV_I4(&paParams[0]) = m_longTypeBarcode;
TV_VT(&paParams[1]) = VTYPE_PWSTR;
paParams[1].pwstrVal = (wchar_t *)&m_wstrBarcode;
paParams[1].wstrLen = wcslen(m_wstrBarcode);
TV_BOOL(pvarRetValue) = true;
} else
{
TV_BOOL(pvarRetValue) = false;
}
return true;
}
default:
return false;
}
return ret;
}
//---------------------------------------------------------------------------//
void CAddInNative::SetLocale(const WCHAR_T* loc)
{
_wsetlocale(LC_ALL, loc);
}
/////////////////////////////////////////////////////////////////////////////
// LocaleBase
//---------------------------------------------------------------------------//
bool CAddInNative::setMemManager(void* mem)
{
m_iMemory = (IMemoryManager*)mem;
return m_iMemory != 0;
}
//---------------------------------------------------------------------------//
void CAddInNative::addError(uint32_t wcode, const wchar_t* source,
const wchar_t* descriptor, long code)
{
if (m_iConnect)
{
WCHAR_T *err = 0;
WCHAR_T *descr = 0;
::convToShortWchar(&err, source);
::convToShortWchar(&descr, descriptor);
m_iConnect->AddError(wcode, err, descr, code);
delete[] err;
delete[] descr;
}
}
//---------------------------------------------------------------------------//
long CAddInNative::findName(wchar_t* names[], const wchar_t* name,
const uint32_t size) const
{
long ret = -1;
for (uint32_t i = 0; i < size; i++)
{
if (!wcscmp(names[i], name))
{
ret = i;
break;
}
}
return ret;
}
//---------------------------------------------------------------------------//
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len)
{
if (!len)
len = ::wcslen(Source)+1;
if (!*Dest)
*Dest = new WCHAR_T[len];
WCHAR_T* tmpShort = *Dest;
wchar_t* tmpWChar = (wchar_t*) Source;
uint32_t res = 0;
::memset(*Dest, 0, len*sizeof(WCHAR_T));
do
{
*tmpShort++ = (WCHAR_T)*tmpWChar++;
++res;
}
while (len-- && *tmpWChar);
return res;
}
//---------------------------------------------------------------------------//
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len)
{
if (!len)
len = getLenShortWcharStr(Source)+1;
if (!*Dest)
*Dest = new wchar_t[len];
wchar_t* tmpWChar = *Dest;
WCHAR_T* tmpShort = (WCHAR_T*)Source;
uint32_t res = 0;
::memset(*Dest, 0, len*sizeof(wchar_t));
do
{
*tmpWChar++ = (wchar_t)*tmpShort++;
++res;
}
while (len-- && *tmpShort);
return res;
}
//---------------------------------------------------------------------------//
uint32_t getLenShortWcharStr(const WCHAR_T* Source)
{
uint32_t res = 0;
WCHAR_T *tmpShort = (WCHAR_T*)Source;
while (*tmpShort++)
++res;
return res;
}
//---------------------------------------------------------------------------//