#define UNICODE #define _WIN32_DCOM
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <initguid.h>
#include "..\idl\ocr.h"
HANDLE g_hExitEvent;
inline ULONG ComponentAddRef()
{
ULONG ul = CoAddRefServerProcess();
wprintf(TEXT("ComponentAddRef(%ld)\n"), ul);
return ul ;
}
inline ULONG ComponentRelease()
{
ULONG ul = CoReleaseServerProcess();
wprintf(TEXT("ComponentRelease(%ld)\n"), ul);
if (ul==0) {
SetEvent(g_hExitEvent);
}
return ul ;
}
void DisplayStatus(wchar_t *pwszMsg, HRESULT hr)
{
if (hr == S_OK) {
wprintf(TEXT("%s\n"), pwszMsg);
return;
}
if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS) {
hr = HRESULT_CODE(hr);
}
wchar_t *pwszStatus;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&pwszStatus,
0,
NULL );
wprintf(TEXT("%s: %s (ECode: %lx)\n"), pwszMsg, pwszStatus, hr);
LocalFree(pwszStatus);
}
inline long ByteLen(wchar_t *pwsz)
{
return (sizeof(wchar_t)*(wcslen(pwsz)+1));
}
void RegisterComponent()
{
wchar_t wszKey[MAX_PATH];
wchar_t wszValue[MAX_PATH];
HKEY hKey = 0;
wcscpy(wszKey, TEXT("CLSID\\{DF22A6B2-A58A-11d1-ABCC-00207810D5FE}"));
RegCreateKey(HKEY_CLASSES_ROOT, wszKey, &hKey);
wcscpy(wszValue, TEXT("OcrEngine"));
RegSetValueEx(hKey, 0, 0, REG_SZ, (BYTE*)wszValue, ByteLen(wszValue));
wcscpy(wszValue, TEXT("{EF20ACA0-C12A-11d1-ABF6-00207810D5FE}"));
RegSetValueEx(hKey, TEXT("AppID"), 0, REG_SZ,
(BYTE*)wszValue, ByteLen(wszValue));
RegCloseKey(hKey);
wcscpy(wszKey, TEXT("CLSID\\{DF22A6B2-A58A-11d1-ABCC-00207810D5FE}\\")
TEXT("LocalServer32"));
RegCreateKey(HKEY_CLASSES_ROOT, wszKey, &hKey);
GetModuleFileName(0, wszValue, MAX_PATH);
RegSetValueEx(hKey, 0, 0, REG_SZ, (BYTE*)wszValue, ByteLen(wszValue));
RegCloseKey(hKey);
wcscpy(wszKey, TEXT("AppID\\ocrsvr.exe"));
RegCreateKey(HKEY_CLASSES_ROOT, wszKey, &hKey);
wcscpy(wszValue, TEXT("{EF20ACA0-C12A-11d1-ABF6-00207810D5FE}"));
RegSetValueEx(hKey, TEXT("AppID"), 0, REG_SZ,
(BYTE*)wszValue, ByteLen(wszValue));
RegCloseKey(hKey);
wcscpy(wszKey, TEXT("AppID\\{EF20ACA0-C12A-11d1-ABF6-00207810D5FE}"));
RegCreateKey(HKEY_CLASSES_ROOT, wszKey, &hKey);
wcscpy(wszValue, TEXT("OcrEngine"));
RegSetValueEx(hKey, 0, 0, REG_SZ,
(BYTE*)wszValue, ByteLen(wszValue));
RegCloseKey(hKey);
}
void UnregisterComponent()
{
long lRc = 0 ;
lRc = RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CLSID\\")
TEXT("{DF22A6B2-A58A-11d1-ABCC-00207810D5FE}\\")
TEXT("LocalServer32"));
DisplayStatus(TEXT("Unregistered LocalServer32"), lRc);
lRc = RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CLSID\\")
TEXT("{DF22A6B2-A58A-11d1-ABCC-00207810D5FE}"));
DisplayStatus(TEXT("Unregistered CLSID"), lRc);
lRc = RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AppID\\")
TEXT("{EF20ACA0-C12A-11d1-ABF6-00207810D5FE}"));
DisplayStatus(TEXT("Unregistered AppID"), lRc);
lRc = RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AppID\\ocrsvr.exe"));
DisplayStatus(TEXT("Unregistered ocrsvr.exe"), lRc);
}
class CoOcrEngine : public IOcr, public ISpell {
public:
CoOcrEngine() : m_lRefCount(0) { ComponentAddRef(); }
~CoOcrEngine() { ComponentRelease(); }
static HRESULT CreateObject(LPUNKNOWN pUnkOuter, REFIID riid,
void** ppv);
public:
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef(void)
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(ULONG) Release(void)
{
long lCount = InterlockedDecrement(&m_lRefCount);
if (lCount == 0) {
delete this;
}
return lCount;
}
STDMETHODIMP OcrImage(long lImageSize,
byte *pbImage,
wchar_t **pwszOcrText);
STDMETHODIMP OcrZone(long lImageSize,
byte *pbImage,
Zone zone,
wchar_t **pwszOcrText);
STDMETHODIMP Check(wchar_t *pwszWord,
PossibleWords *pWords);
private:
LONG m_lRefCount;
};
HRESULT CoOcrEngine::CreateObject(LPUNKNOWN pUnkOuter,
REFIID riid,
void** ppv)
{
*ppv = NULL;
if (pUnkOuter != NULL) { return CLASS_E_NOAGGREGATION; }
CoOcrEngine * pEngine = new CoOcrEngine;
if (pEngine == NULL) { return E_OUTOFMEMORY; }
HRESULT hr = pEngine->QueryInterface(riid, ppv);
if (FAILED(hr)) { delete pEngine; }
return hr;
}
STDMETHODIMP
CoOcrEngine::QueryInterface(REFIID riid, void** ppv)
{
if (ppv==NULL) { return E_INVALIDARG; }
wchar_t *pIID=0;
StringFromIID(riid, &pIID);
wprintf(TEXT("CoOcrEngine::QueryInterface[%s]\n"), pIID);
CoTaskMemFree(pIID);
if (riid==IID_IUnknown) {
*ppv= static_cast<IOcr *>(this);
} else if (riid==IID_IOcr) {
*ppv= static_cast<IOcr *>(this);
} else if (riid==IID_ISpell) {
*ppv= static_cast<ISpell *>(this);
} else {
*ppv=NULL; return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP
CoOcrEngine::OcrImage(long lImageSize,
byte *pbImage,
wchar_t **pwszOcrText)
{
wchar_t wszPath[MAX_PATH];
GetTempPath(MAX_PATH, wszPath);
wchar_t wszFileName[MAX_PATH];
GetTempFileName(wszPath, TEXT("TIF"), 0, wszFileName);
DisplayStatus(wszFileName, S_OK);
HANDLE hFile = CreateFile(wszFileName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile==INVALID_HANDLE_VALUE) {
Beep(1000,1000);
wprintf(TEXT("hFile invalid\n"));
} else {
DWORD dwWritten = 0 ;
WriteFile(hFile,
static_cast<LPCVOID>(pbImage),
lImageSize,
&dwWritten, NULL);
CloseHandle(hFile);
}
wchar_t wszOcrText[MAX_PATH];
wcscpy(wszOcrText, TEXT("This is fake OCR text"));
long lAllocSize = (wcslen(wszOcrText)+1) * sizeof(wchar_t);
wprintf(TEXT("lAllocSize = %u\n"), lAllocSize);
*pwszOcrText = static_cast<wchar_t *>(CoTaskMemAlloc(lAllocSize));
if (*pwszOcrText==NULL) { return E_OUTOFMEMORY; }
wcscpy(*pwszOcrText, wszOcrText);
wprintf(TEXT("Returning = %s\n"), *pwszOcrText);
return S_OK ;
}
STDMETHODIMP
CoOcrEngine::OcrZone(long lImageSize, byte *pbImage,
Zone zone, wchar_t **pwszOcrText)
{
return E_NOTIMPL ;
}
STDMETHODIMP
CoOcrEngine::Check(wchar_t *pszWord, PossibleWords *pWords)
{
wcscpy(reinterpret_cast<wchar_t *>(pWords->wszOne), TEXT("ChoiceOne"));
wcscpy(reinterpret_cast<wchar_t *>(pWords->wszTwo), TEXT("ChoiceTwo"));
return S_OK ;
}
class CoOcrEngineFactory : public IClassFactory
{
public:
STDMETHODIMP QueryInterface (REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef(void)
{ return 1; }
STDMETHODIMP_(ULONG) Release(void)
{ return 1; }
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,
REFIID riid,
void **ppv)
{
return CoOcrEngine::CreateObject(pUnkOuter, riid, ppv);
}
STDMETHODIMP LockServer(BOOL fLock)
{
if (fLock) {
ComponentAddRef();
} else {
ComponentRelease();
}
return S_OK;
}
};
CoOcrEngineFactory g_OcrEngineClassFactory;
STDMETHODIMP
CoOcrEngineFactory::QueryInterface(REFIID riid, void** ppv)
{
if (ppv==NULL) { return E_INVALIDARG; }
wchar_t *pIID=0;
StringFromIID(riid, &pIID);
wprintf(TEXT("CoOcrEngineFactory::QueryInterface[%s]\n"), pIID);
CoTaskMemFree(pIID);
if (riid==IID_IUnknown) {
*ppv= static_cast<IClassFactory *>(this);
} else if (riid==IID_IClassFactory) {
*ppv= static_cast<IClassFactory *>(this);
} else {
*ppv=NULL; return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
return S_OK;
}
void main(int argc, char **argv)
{
DisplayStatus(TEXT("Server: Started"), S_OK);
g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
assert(g_hExitEvent);
if (argc > 1) {
if (_stricmp(argv[1], "-RegServer")==0){
RegisterComponent();
DisplayStatus(TEXT("Registered..."), S_OK);
return ;
}
if (_stricmp(argv[1], "-UnRegServer")==0){
UnregisterComponent();
DisplayStatus(TEXT("Unregistered..."), S_OK);
return ;
}
}
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
assert(SUCCEEDED(hr));
DWORD dwRegister;
hr = CoRegisterClassObject(CLSID_OcrEngine,
&g_OcrEngineClassFactory,
CLSCTX_SERVER,
REGCLS_MULTIPLEUSE,
&dwRegister);
assert(SUCCEEDED(hr));
g_OcrEngineClassFactory.Release();
WaitForSingleObject(g_hExitEvent, INFINITE);
CoRevokeClassObject(dwRegister);
CoUninitialize();
DisplayStatus(TEXT("Server shutting down in 5 seconds..."), S_OK);
Sleep(5000);
}