#define WINVER 0x0501
#define _WIN32_WINNT 0x0501	
#define _WIN32_WINDOWS 0x0410
#define _WIN32_IE 0x0600
#define WIN32_LEAN_AND_MEAN

// Необходим для "::CoInitializeEx(NULL,COINIT_MULTITHREADED);" 
#define _WIN32_DCOM

#include <stdio.h>
#include <tchar.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlfile.h>
#include <string>
#include <time.h>

#import "progid:NiApi.SrvrSession"  rename_namespace("NiApi")
using namespace NiApi;


#include "SrvrSessionEvents.h"
#include "TableEvents.h"
#include "TableEventsFast.h"

ISrvrSessionPtr*	g_ppSession = 0;


int _tmain(int argc, _TCHAR* argv)
{
	::CoInitializeEx(NULL, COINIT_MULTITHREADED);

	{
		CSrvrSessionEvents		SessionEvents;
		ISrvrSessionPtr			pSession(__uuidof(SrvrSession));
		SessionEvents.DispEventAdvise(pSession, &DIID__ISrvrSessionEvents);

		pSession->HostAddr = _bstr_t("nidemo.mfd.ru");
		pSession->HostPort = 2900;
		pSession->Name = _bstr_t("login");
		pSession->Password = _bstr_t("pass");
		// если интересно что происходит, включаем журнал протокола
		pSession->Journal = _bstr_t("journal");
		printf("Calling Connect()...[%d]\n", GetCurrentThreadId());
		pSession->Connect();

		::Sleep(2000);

		if (SessionEvents.m_bConnect)
		{
			CTableEvents			TableEventsAllTrades, TableEventsOrders, TableEventsDeals, TableEventsPortfolio;
			ITablePtr				pTableAllTrades(__uuidof(Table));
			ITablePtr				pTableOrders(__uuidof(Table));
			ITablePtr				pTableDeals(__uuidof(Table));
			ITablePtr				pTablePortfolio(__uuidof(Table));
			TableEventsAllTrades.DispEventAdvise(pTableAllTrades, &DIID__ITableEvents);
			TableEventsOrders.DispEventAdvise(pTableOrders, &DIID__ITableEvents);
			TableEventsDeals.DispEventAdvise(pTableDeals, &DIID__ITableEvents);
			TableEventsPortfolio.DispEventAdvise(pTablePortfolio, &DIID__ITableEvents);

			try
			{
				// открываем таблицу
				pTableAllTrades->Open(pSession, "ALL_TRADES_PSFU", tabNoneAddr); // Таблица ALL_TRADES_PSFU безадресная (tabNoneAddr, т.е. не привязана к конкретному пользователю)

				char s[1024];

				IFilterPtr	pFilter(__uuidof(Filter));
				pFilter->PutStructure(pTableAllTrades->GetStructure());


				// Запрос среза с фильтром
				/*
				_snprintf(s, 1024, "10:00:00");
				variant_t d("I_TIME"), v(s);
				pFilter->Add(&d, conGreater, &v);

				_snprintf(s, 1024, "Si");
				variant_t d2("I_NAME"), v2(s);
				pFilter->Add(&d2, conEqual, &v2);

				variant_t Filter;
				Filter.vt = VT_DISPATCH;
				Filter.pdispVal = pFilter;

				pTableAllTrades->GetSlice(Filter);

				Filter.Detach();
				*/

				// Запрос среза без фильтра
				pTableAllTrades->GetSlice();

				variant_t d("I_NAME"), v1("Si"), v2("RTS"), v3("LKOH-6.17");

				// Добавляем фильтр на обновления. Если I_NAME = "Si" или "RTS" т.е. получаем все текущие сделки по Si и по RTS.
				pTableAllTrades->AddUpdateFilter(0, logOr, &d, conEqual, &v1); 
				pTableAllTrades->AddUpdateFilter(0, logOr, &d, conEqual, &v2);
				pTableAllTrades->AddUpdateFilter(0, logOr, &d, conEqual, &v3);
				pTableAllTrades->SetOnlineUpdates(subEnabled);

				// Заявки FORTS
				pTableOrders->Open(pSession, "ORDERS_PSFU", tabAdrr); // Таблица ORDERS_PSFU адресная (tabAddr, т.е. завязана на конкретного пользователя)
				pTableOrders->GetData(); // Получаем историю по таблице
				pTableOrders->SetOnlineUpdates(subEnabled); // Подписываемся на обновления
															// Сделки FORTS
				pTableDeals->Open(pSession, "DEALS_PSFU", tabAdrr);
				pTableDeals->GetData();
				pTableDeals->SetOnlineUpdates(subEnabled);
				// Портфель
				pTablePortfolio->Open(pSession, "PORTFOLIO_PSFU", tabAdrr);
				pTablePortfolio->GetData();
				pTablePortfolio->SetOnlineUpdates(subEnabled);

				// Выставляем заявку
				ITransactionPtr pTrans(__uuidof(Transaction));
				IDataRowPtr pRow(__uuidof(DataRow));
				pTrans->Open(pSession, "FUTADDORDER", tabAdrr); // Созда
				pRow->PutStructure(pTrans->GetStructure());
				variant_t SECCODE = "I_SECCODE";
				variant_t SECCODE_VAL = "LKOH-6.17";
				pRow->put_Item(&SECCODE, SECCODE_VAL);   // Код инструмента                                
				variant_t BUYSELL = "I_BUYSELL";
				variant_t BUYSELL_VAL = "B";
				pRow->put_Item(&BUYSELL, BUYSELL_VAL);    // Направление: B – покупка, S – продажа                
				variant_t QUANTITY = "I_QUANTITY";
				variant_t QUANTITY_VAL = "1";
				pRow->put_Item(&QUANTITY, QUANTITY_VAL);  //Количество                                             
				variant_t PRICE = "I_PRICE";
				variant_t PRICE_VAL = "28350";
				pRow->put_Item(&PRICE, PRICE_VAL); // Цена                                                
				variant_t MKTLIMIT = "I_MKTLIMIT";
				variant_t MKTLIMIT_VAL = "M";
				pRow->put_Item(&MKTLIMIT, MKTLIMIT_VAL);  //Тип заявки: M - котировочная, L - встречная            
				variant_t BROKERREF = "I_BROKERREF";
				variant_t BROKERREF_VAL = "997";
				pRow->put_Item(&BROKERREF, BROKERREF_VAL);  //Счет       

				variant_t ACCOUNT = "I_ACCOUNT";
				variant_t ACCOUNT_VAL = "MF00";
				pRow->put_Item(&ACCOUNT, ACCOUNT_VAL);  //Счет       

				pTrans->Execute(pRow);
				
				// Работаем дальше и ожидаем нажатия любой клавиши.
				getchar();

				TableEventsAllTrades.DispEventUnadvise(pTableAllTrades, &DIID__ITableEvents);
				TableEventsOrders.DispEventUnadvise(pTableOrders, &DIID__ITableEvents);
				TableEventsDeals.DispEventUnadvise(pTableDeals, &DIID__ITableEvents);
				TableEventsPortfolio.DispEventUnadvise(pTablePortfolio, &DIID__ITableEvents);
			}
			catch (_com_error e)
			{
				printf("%s", e.ErrorMessage());
				if (e.ErrorInfo())
				{
					BSTR desc;
					e.ErrorInfo()->GetDescription(&desc);
					printf("%s", desc);
				}
			}
			catch (...)
			{
				printf("Unknown exception");
			}
		}

		if (SessionEvents.m_bConnect)
			pSession->Disconnect();

		::Sleep(2000);

		SessionEvents.DispEventUnadvise(pSession, &DIID__ISrvrSessionEvents);
	}

	::CoUninitialize();
	return 0;
}