static bool Connect(PyObject* pConnectString, HDBC hdbc, bool fAnsi) { // This should have been checked by the global connect function. I(PyString_Check(pConnectString) || PyUnicode_Check(pConnectString)); const int cchMax = 600; if (PySequence_Length(pConnectString) >= cchMax) { PyErr_SetString(PyExc_TypeError, "connection string too long"); return false; } // The driver manager determines if the app is a Unicode app based on whether we call SQLDriverConnectA or // SQLDriverConnectW. Some drivers, notably Microsoft Access/Jet, change their behavior based on this, so we try // the Unicode version first. (The Access driver only supports Unicode text, but SQLDescribeCol returns SQL_CHAR // instead of SQL_WCHAR if we connect with the ANSI version. Obviously this causes lots of errors since we believe // what it tells us (SQL_CHAR).) // Python supports only UCS-2 and UCS-4, so we shouldn't need to worry about receiving surrogate pairs. However, // Windows does use UCS-16, so it is possible something would be misinterpreted as one. We may need to examine // this more. SQLRETURN ret; if (!fAnsi) { SQLWCHAR szConnectW[cchMax]; if (PyUnicode_Check(pConnectString)) { Py_UNICODE* p = PyUnicode_AS_UNICODE(pConnectString); for (int i = 0, c = PyUnicode_GET_SIZE(pConnectString); i <= c; i++) szConnectW[i] = (wchar_t)p[i]; } else { const char* p = PyString_AS_STRING(pConnectString); for (int i = 0, c = PyString_GET_SIZE(pConnectString); i <= c; i++) szConnectW[i] = (wchar_t)p[i]; } Py_BEGIN_ALLOW_THREADS ret = SQLDriverConnectW(hdbc, 0, szConnectW, SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT); Py_END_ALLOW_THREADS if (SQL_SUCCEEDED(ret)) return true; // The Unicode function failed. If the error is that the driver doesn't have a Unicode version (IM001), continue // to the ANSI version. PyObject* error = GetErrorFromHandle("SQLDriverConnectW", hdbc, SQL_NULL_HANDLE); if (!HasSqlState(error, "IM001")) { RaiseErrorFromException(error); return false; } Py_XDECREF(error); }
int ODBC_Connect (char *connStr) { short buflen; SQLCHAR dataSource[1024]; SQLTCHAR dsn[33]; SQLTCHAR desc[255]; SQLTCHAR driverInfo[255]; SQLSMALLINT len1, len2; int status; #ifdef UNICODE SQLWCHAR wdataSource[1024]; #endif #if (ODBCVER < 0x0300) if (SQLAllocEnv (&henv) != SQL_SUCCESS) return -1; if (SQLAllocConnect (henv, &hdbc) != SQL_SUCCESS) return -1; #else if (SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv) != SQL_SUCCESS) return -1; SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER); if (SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc) != SQL_SUCCESS) return -1; #endif /* * Set the application name */ SQLSetConnectOption (hdbc, SQL_APPLICATION_NAME, (SQLULEN) TEXT ("odbctest")); /* * Show the version number of the driver manager */ status = SQLGetInfo (hdbc, SQL_DM_VER, driverInfo, sizeof (driverInfo), &len1); if (status == SQL_SUCCESS) { #ifdef UNICODE printf ("Driver Manager: %S\n", driverInfo); #else printf ("Driver Manager: %s\n", driverInfo); #endif } /* * Either use the connect string provided on the command line or * ask for one. If an empty string or a ? is given, show a nice * list of options */ if (connStr && *connStr) strcpy ((char *) dataSource, connStr); else while (1) { /* * Ask for the connect string */ printf ("\nEnter ODBC connect string (? shows list): "); if (fgets ((char *) dataSource, sizeof (dataSource), stdin) == NULL) return 1; /* * Remove trailing '\n' */ dataSource[strlen ((char *) dataSource) - 1] = '\0'; /* * Check if the user wants to quit */ if (!strcmp ((char *)dataSource, "quit") || !strcmp ((char *)dataSource, "exit")) return -1; /* * If the user entered something other than a ? * break out of the while loop */ if (*dataSource && *dataSource != '?') break; /* * Print headers */ fprintf (stderr, "\n%-32s | %-40s\n", "DSN", "Driver"); fprintf (stderr, "------------------------------------------------------------------------------\n"); /* * Goto the first record */ if (SQLDataSources (henv, SQL_FETCH_FIRST, dsn, NUMTCHAR (dsn), &len1, desc, NUMTCHAR (desc), &len2) != SQL_SUCCESS) continue; /* * Show all records */ do { #ifdef UNICODE fprintf (stderr, "%-32S | %-40S\n", dsn, desc); #else fprintf (stderr, "%-32s | %-40s\n", dsn, desc); #endif } while (SQLDataSources (henv, SQL_FETCH_NEXT, dsn, NUMTCHAR (dsn), &len1, desc, NUMTCHAR (desc), &len2) == SQL_SUCCESS); } #ifdef UNICODE strcpy_A2W (wdataSource, (char *) dataSource); status = SQLDriverConnectW (hdbc, 0, (SQLWCHAR *) wdataSource, SQL_NTS, (SQLWCHAR *) outdsn, NUMTCHAR (outdsn), &buflen, SQL_DRIVER_COMPLETE); if (status != SQL_SUCCESS) ODBC_Errors ("SQLDriverConnectW"); #else status = SQLDriverConnect (hdbc, 0, (SQLCHAR *) dataSource, SQL_NTS, (SQLCHAR *) outdsn, NUMTCHAR (outdsn), &buflen, SQL_DRIVER_COMPLETE); if (status != SQL_SUCCESS) ODBC_Errors ("SQLDriverConnect"); #endif if (status != SQL_SUCCESS && status != SQL_SUCCESS_WITH_INFO) return -1; connected = 1; /* * Print out the version number and the name of the connected driver */ status = SQLGetInfo (hdbc, SQL_DRIVER_VER, driverInfo, NUMTCHAR (driverInfo), &len1); if (status == SQL_SUCCESS) { #ifdef UNICODE printf ("Driver: %S", driverInfo); #else printf ("Driver: %s", driverInfo); #endif status = SQLGetInfo (hdbc, SQL_DRIVER_NAME, driverInfo, NUMTCHAR (driverInfo), &len1); if (status == SQL_SUCCESS) { #ifdef UNICODE printf (" (%S)", driverInfo); #else printf (" (%s)", driverInfo); #endif } printf ("\n"); } /* * Show the list of supported functions in trace log */ #if (ODBCVER < 0x0300) { SQLUSMALLINT exists[100]; SQLGetFunctions (hdbc, SQL_API_ALL_FUNCTIONS, exists); } #else { SQLUSMALLINT exists[SQL_API_ODBC3_ALL_FUNCTIONS_SIZE]; SQLGetFunctions (hdbc, SQL_API_ODBC3_ALL_FUNCTIONS, exists); } #endif /* * Allocate statement handle */ #if (ODBCVER < 0x0300) if (SQLAllocStmt (hdbc, &hstmt) != SQL_SUCCESS) return -1; #else if (SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt) != SQL_SUCCESS) return -1; #endif return 0; }
static bool Connect(PyObject* pConnectString, HDBC hdbc, bool fAnsi, long timeout) { // This should have been checked by the global connect function. I(PyString_Check(pConnectString) || PyUnicode_Check(pConnectString)); const int cchMax = 600; if (PySequence_Length(pConnectString) >= cchMax) { PyErr_SetString(PyExc_TypeError, "connection string too long"); return false; } // The driver manager determines if the app is a Unicode app based on whether we call SQLDriverConnectA or // SQLDriverConnectW. Some drivers, notably Microsoft Access/Jet, change their behavior based on this, so we try // the Unicode version first. (The Access driver only supports Unicode text, but SQLDescribeCol returns SQL_CHAR // instead of SQL_WCHAR if we connect with the ANSI version. Obviously this causes lots of errors since we believe // what it tells us (SQL_CHAR).) // Python supports only UCS-2 and UCS-4, so we shouldn't need to worry about receiving surrogate pairs. However, // Windows does use UCS-16, so it is possible something would be misinterpreted as one. We may need to examine // this more. SQLRETURN ret; if (timeout > 0) { //Py_BEGIN_ALLOW_THREADS ret = SQLSetConnectAttr(hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)timeout, SQL_IS_UINTEGER); //Py_END_ALLOW_THREADS if (!SQL_SUCCEEDED(ret)) RaiseErrorFromHandle("SQLSetConnectAttr(SQL_ATTR_LOGIN_TIMEOUT)", hdbc, SQL_NULL_HANDLE); } if (!fAnsi) { SQLWChar connectString(pConnectString); //Py_BEGIN_ALLOW_THREADS ret = SQLDriverConnectW(hdbc, 0, connectString.get(), (SQLSMALLINT)connectString.size(), 0, 0, 0, SQL_DRIVER_NOPROMPT); //Py_END_ALLOW_THREADS if (SQL_SUCCEEDED(ret)) return true; RaiseErrorFromHandle("SQLDriverConnect", hdbc, SQL_NULL_HANDLE); return false; // The Unicode function failed. If the error is that the driver doesn't have a Unicode version (IM001), continue // to the ANSI version. // // I've commented this out since a number of common drivers are returning different errors. The MySQL 5 // driver, for example, returns IM002 "Data source name not found...". // // PyObject* error = GetErrorFromHandle("SQLDriverConnectW", hdbc, SQL_NULL_HANDLE); // if (!HasSqlState(error, "IM001")) // { // RaiseErrorFromException(error); // return false; // } // Py_XDECREF(error); } PyErr_SetString(PyExc_TypeError, "Non-unicode connection strings not supported."); return false; }
__declspec(dllexport) BOOL SoaronModuleFunc(void) { SQLHDBC hdbc; HSTMT hstmt; unsigned int NumOfLinks, LinkID; WSADATA wd; SQLRETURN sqlret; HANDLE hHeap; FTNAddr LinkAddr; wchar_t Ip[256]; lpLinksCheckInfo LinksTable; WSAEVENT * EventsTable; WSANETWORKEVENTS evt; unsigned int i, j; int res; ADDRINFOW *result = NULL; ADDRINFOW hints; wchar_t LogStr[255]; memset(&hints, 0, sizeof(hints)); LinkAddr.point = 0; NumOfLinks = 0; SQLAllocHandle(SQL_HANDLE_DBC, cfg.henv, &hdbc); sqlret = SQLDriverConnectW(hdbc, NULL, cfg.ConnectionString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (sqlret != SQL_SUCCESS && sqlret != SQL_SUCCESS_WITH_INFO) { SetEvent(cfg.hExitEvent); return FALSE;//fatal error } SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); AddLogEntry(L"Checking binkp links alive"); //get links info SQLExecDirectW(hstmt, L"update Links set DialOut=0 where datediff(minute,LastSessionTime,GetDate())>40 and LinkType=1", SQL_NTS); sqlret = SQLExecDirectW(hstmt, L"select count(*) from Links where dialout=0 and passivelink=0 and LinkType=1 and isnull(ip,'')<>''", SQL_NTS); if ((sqlret == SQL_SUCCESS) || (sqlret = SQL_SUCCESS_WITH_INFO)) { sqlret = SQLFetch(hstmt); if ((sqlret == SQL_SUCCESS) || (sqlret = SQL_SUCCESS_WITH_INFO)) { SQLGetData(hstmt, 1, SQL_C_ULONG, &NumOfLinks, 0, NULL); } } SQLCloseCursor(hstmt); if (NumOfLinks == 0) goto exit; hHeap = HeapCreate(HEAP_NO_SERIALIZE, 8192, 0); LinksTable = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, NumOfLinks*sizeof(LinksCheckInfo)); EventsTable = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(WSAEVENT)*NumOfLinks); i = 0; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; WSAStartup(MAKEWORD(2, 2), &wd); sqlret = SQLExecDirectW(hstmt, L"select LinkID,Zone,Net,Node, Ip from Links where dialout=0 and passivelink=0 and LinkType=1 and isnull(ip,'')<>''", SQL_NTS); if ((sqlret == SQL_SUCCESS) || (sqlret = SQL_SUCCESS_WITH_INFO)) { SQLBindCol(hstmt, 1, SQL_C_ULONG, &LinkID, 0, NULL); SQLBindCol(hstmt, 2, SQL_C_USHORT, &(LinkAddr.zone), 0, NULL); SQLBindCol(hstmt, 3, SQL_C_USHORT, &(LinkAddr.net), 0, NULL); SQLBindCol(hstmt, 4, SQL_C_USHORT, &(LinkAddr.node), 0, NULL); SQLBindCol(hstmt, 5, SQL_C_WCHAR, Ip, 512, NULL); sqlret = SQLFetch(hstmt); while ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { // res = GetAddrInfoW(Ip, L"24554", &hints, &result); if (res == 0) { memcpy(&(LinksTable[i].sa), result->ai_addr, sizeof(struct sockaddr_in)); // printf("%u %u %S %u.%u.%u.%u\n", i,LinkID, Ip, LinksTable[i].sa.sin_addr.S_un.S_un_b.s_b1, LinksTable[i].sa.sin_addr.S_un.S_un_b.s_b2, LinksTable[i].sa.sin_addr.S_un.S_un_b.s_b3, LinksTable[i].sa.sin_addr.S_un.S_un_b.s_b4); LinksTable[i].LinkID = LinkID; LinksTable[i].LinkAddr.FullAddr = LinkAddr.FullAddr; LinksTable[i].s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); EventsTable[i] = WSACreateEvent(); WSAEventSelect(LinksTable[i].s, EventsTable[i], FD_CONNECT); FreeAddrInfoW(result); ++i; } else { wsprintfW(LogStr,L"%u:%u/%u: Ip address %s cannot be resolved", LinkAddr.zone, LinkAddr.net, LinkAddr.node,Ip); AddLogEntry(LogStr); } sqlret = SQLFetch(hstmt); } } SQLCloseCursor(hstmt); SQLFreeStmt(hstmt, SQL_UNBIND); NumOfLinks = i; for (i = 0; i < NumOfLinks; i++) { connect(LinksTable[i].s, (struct sockaddr *)&(LinksTable[i].sa), sizeof(struct sockaddr_in)); } j = 0; SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &LinkID, 0, NULL); SQLPrepareW(hstmt, L"Update Links set DialOut=1 where LinkID=?", SQL_NTS); while (j < NumOfLinks) { res = WSAWaitForMultipleEvents(NumOfLinks, EventsTable, FALSE, WSA_INFINITE, FALSE); WSAEnumNetworkEvents(LinksTable[res].s, EventsTable[res], &evt); shutdown(LinksTable[res].s, SD_BOTH); closesocket(LinksTable[res].s); if (evt.iErrorCode[FD_CONNECT_BIT] == 0) { wsprintfW(LogStr, L"%u:%u/%u: OK", LinksTable[res].LinkAddr.zone, LinksTable[res].LinkAddr.net, LinksTable[res].LinkAddr.node); LinkID = LinksTable[res].LinkID; SQLExecute(hstmt); } else { switch (evt.iErrorCode[FD_CONNECT_BIT]) { case WSAECONNREFUSED: wsprintfW(LogStr, L"%u:%u/%u: Connection refused", LinksTable[res].LinkAddr.zone, LinksTable[res].LinkAddr.net, LinksTable[res].LinkAddr.node); break; case WSAETIMEDOUT: wsprintfW(LogStr, L"%u:%u/%u: Connection timed out", LinksTable[res].LinkAddr.zone, LinksTable[res].LinkAddr.net, LinksTable[res].LinkAddr.node); break; default:wsprintfW(LogStr, L"%u:%u/%u: Unknown connection error", LinksTable[res].LinkAddr.zone, LinksTable[res].LinkAddr.net, LinksTable[res].LinkAddr.node); } } AddLogEntry(LogStr); ++j; } // for (j = 0; j < NumOfLinks; j++) { WSACloseEvent(EventsTable[j]); } SQLFreeStmt(hstmt, SQL_RESET_PARAMS); // WSACleanup(); HeapDestroy(hHeap); exit: SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); AddLogEntry(L"Links alive check done"); SetEvent(cfg.hLinksUpdateEvent); return TRUE; }
void LogSessionAndSendNetmailToLink(lpFTNAddr lpLinkAddr, unsigned char SoftwareCode) { SQLHDBC hdbc; SQLHSTMT hstmt; SQLRETURN sqlret; SQLLEN cb; HANDLE hHeap; HANDLE hPktFile; wchar_t tmpPktFileName[MAX_PATH], finalPktFileName[MAX_PATH], FileboxDirName[MAX_PATH]; wchar_t LogStr[255]; unsigned int PktNumber; unsigned int LinkID; NetmailOutQueue NOQ; char PktPwd[9]; hHeap = HeapCreate(HEAP_NO_SERIALIZE, 16384, 0); SQLAllocHandle(SQL_HANDLE_DBC, cfg.henv, &hdbc); sqlret = SQLDriverConnectW(hdbc, NULL, cfg.ConnectionString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (sqlret != SQL_SUCCESS && sqlret != SQL_SUCCESS_WITH_INFO) { SetEvent(cfg.hExitEvent); return; //fatal error } SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &LinkID, 0, NULL); SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(lpLinkAddr->zone), 0, NULL); SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(lpLinkAddr->net), 0, NULL); SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(lpLinkAddr->node), 0, NULL); SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(lpLinkAddr->point), 0, NULL); SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_UTINYINT , SQL_TINYINT, 0, 0, &SoftwareCode, 0, NULL); SQLExecDirectW(hstmt, L"{?=call sp_GetLinkIdForNetmailRouting(?,?,?,?,?)}", SQL_NTS); NOQ.First = NULL; NOQ.Last = NULL; SQLFreeStmt(hstmt, SQL_RESET_PARAMS); if (SoftwareCode != 1) goto exit; if (LinkID != 0) { //netmail out// memset(PktPwd, 0, 9); SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &LinkID, 0, NULL); sqlret = SQLExecDirectW(hstmt, L"select PktPassword from Links where LinkID=?", SQL_NTS);// if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { sqlret = SQLFetch(hstmt); if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { SQLGetData(hstmt, 1, SQL_C_CHAR, PktPwd, 9, &cb); } } SQLCloseCursor(hstmt); EnterCriticalSection(&NetmailRouteCritSect); sqlret = SQLExecDirectW(hstmt, L"select Netmail.MessageID,FromZone,FromNet,FromNode,FromPoint,ToZone,ToNet,ToNode,ToPoint,CreateTime,FromName,ToName,Subject,MsgId,ReplyTo,MsgText,KillSent,Pvt,FileAttach,Arq,RRq,ReturnReq,Direct,Cfm,recv from Netmail,NetmailOutbound where Netmail.MessageID=NetmailOutbound.MessageID and NetmailOutbound.ToLinkID=? order by Netmail.MessageID", SQL_NTS);// if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { GetNetmailMessages(hstmt, hHeap, &NOQ); } SQLFreeStmt(hstmt, SQL_RESET_PARAMS); if (NOQ.First != NULL) { PktNumber = GetPktNumber(hstmt); wsprintfW(FileboxDirName, L"%s\\%u.%u.%u.0", cfg.FileboxesDir, lpLinkAddr->zone, lpLinkAddr->net, lpLinkAddr->node); wsprintfW(tmpPktFileName, L"%s\\%08X.NETMAIL", cfg.TmpOutboundDir, PktNumber); wsprintfW(finalPktFileName, L"%s\\%08X.PKT", FileboxDirName, PktNumber); hPktFile = CreateFileW(tmpPktFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); WritePktHeader(hPktFile, &(cfg.MyAddr),lpLinkAddr, PktPwd); // while (NOQ.First != NULL) { lpNetmailMessage lpTmp; // wsprintfW(LogStr, L"Dynamic netmail %u:%u/%u.%u -> %u:%u/%u.%u thru %u:%u/%u", NOQ.First->FromAddr.zone, NOQ.First->FromAddr.net, NOQ.First->FromAddr.node, NOQ.First->FromAddr.point, NOQ.First->ToAddr.zone, NOQ.First->ToAddr.net, NOQ.First->ToAddr.node, NOQ.First->ToAddr.point, lpLinkAddr->zone, lpLinkAddr->net, lpLinkAddr->node); AddLogEntry(LogStr); WriteNetmailMessage(hPktFile, hHeap, NOQ.First); SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &(NOQ.First->MessageID), 0, NULL); sqlret = SQLExecDirectW(hstmt, L"{call sp_NetmailMessageSent(?)}", SQL_NTS); SQLFreeStmt(hstmt, SQL_RESET_PARAMS); // lpTmp = NOQ.First->NextMsg; HeapFree(hHeap, 0, NOQ.First->MsgText); if (NOQ.First->ReplyTo != NULL) HeapFree(hHeap, 0, NOQ.First->ReplyTo); if (NOQ.First->MsgId != NULL) HeapFree(hHeap, 0, NOQ.First->MsgId); HeapFree(hHeap, 0, NOQ.First->Subject); HeapFree(hHeap, 0, NOQ.First->ToName); HeapFree(hHeap, 0, NOQ.First->FromName); HeapFree(hHeap, 0, NOQ.First); NOQ.First = lpTmp; } if (hPktFile != INVALID_HANDLE_VALUE) { ClosePktFile(hPktFile); CreateDirectoryW(FileboxDirName, NULL); MoveFileExW(tmpPktFileName, finalPktFileName, MOVEFILE_COPY_ALLOWED); } // } LeaveCriticalSection(&NetmailRouteCritSect); } exit: SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); HeapDestroy(hHeap); }
DWORD WINAPI NetmailOutThread(LPVOID param) { SQLHDBC hdbc; SQLHSTMT hstmt; SQLRETURN sqlret; SQLLEN cb; HANDLE hHeap; FTNAddr LastAddr; HANDLE hPktFile; wchar_t tmpFileName[MAX_PATH], finalPktFileName[MAX_PATH],FileboxDirName[MAX_PATH]; wchar_t LogStr[255]; unsigned int PktNumber; char PktPwd[9]; NetmailOutQueue NDOQ; int WaitTime; int result; HANDLE hEvent[2]; InterlockedIncrement(&(cfg.ThreadCount)); WaitTime=INFINITE; hEvent[0]=cfg.hExitEvent; hEvent[1]=cfg.hNetmailOutEvent; AddLogEntry(L"Netmail out thread started"); loop: result=WaitForMultipleObjects(2,hEvent,FALSE,WaitTime); if (result==WAIT_TIMEOUT) { SQLFreeHandle(SQL_HANDLE_STMT,hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); WaitTime=INFINITE; HeapDestroy(hHeap); goto loop; } if (WaitTime==INFINITE) { hHeap=HeapCreate(HEAP_NO_SERIALIZE,16384,0); SQLAllocHandle(SQL_HANDLE_DBC, cfg.henv, &hdbc); sqlret=SQLDriverConnectW(hdbc, NULL, cfg.ConnectionString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (sqlret != SQL_SUCCESS && sqlret != SQL_SUCCESS_WITH_INFO) { SetEvent(cfg.hExitEvent); goto threadexit; //fatal error } SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); WaitTime=10000; } switch(result) { case (WAIT_OBJECT_0): { goto threadexit; } case (WAIT_OBJECT_0+1): { NDOQ.First=NULL; NDOQ.Last=NULL; EnterCriticalSection(&NetmailRouteCritSect); SQLExecDirectW(hstmt, L"execute sp_DirectNetmail", SQL_NTS); // обработать директный нетмейл для использующих FTN Service линков LeaveCriticalSection(&NetmailRouteCritSect); sqlret=SQLExecDirectW(hstmt,L"select MessageID,FromZone,FromNet,FromNode,FromPoint,ToZone,ToNet,ToNode,ToPoint,CreateTime,FromName,ToName,Subject,MsgId,ReplyTo,MsgText,KillSent,Pvt,FileAttach,Arq,RRq,ReturnReq,Direct,Cfm,recv from Netmail where direct=1 and sent=0 and Locked=0 order by ToZone,ToNet,ToNode,MessageID",SQL_NTS); if ((sqlret==SQL_SUCCESS)||(sqlret==SQL_SUCCESS_WITH_INFO)) { GetNetmailMessages(hstmt,hHeap,&NDOQ); } sqlret=SQLExecDirectW(hstmt,L"select MessageID,FromZone,FromNet,FromNode,FromPoint,ToZone,ToNet,ToNode,ToPoint,CreateTime,FromName,ToName,Subject,MsgId,ReplyTo,MsgText,KillSent,Pvt,FileAttach,Arq,RRq,ReturnReq,Direct,Cfm,recv from Netmail,MyAka where direct=0 and sent=0 and Locked=0 and MyAka.Point=0 and Netmail.ToPoint<>0 and Netmail.ToZone=MyAka.Zone and Netmail.ToNet=MyAka.Net and Netmail.ToNode=MyAka.Node order by ToPoint,MessageID",SQL_NTS); if ((sqlret==SQL_SUCCESS)||(sqlret==SQL_SUCCESS_WITH_INFO)) { GetNetmailMessages(hstmt, hHeap, &NDOQ); } sqlret = SQLExecDirectW(hstmt, L"select MessageID,FromZone,FromNet,FromNode,FromPoint,ToZone,ToNet,ToNode,ToPoint,CreateTime,FromName,ToName,Subject,MsgId,ReplyTo,MsgText,KillSent,Pvt,FileAttach,Arq,RRq,ReturnReq,Direct,Cfm,recv from Netmail,Links where direct=0 and sent=0 and Locked=0 and Netmail.ToZone=Links.Zone and Netmail.ToNet=Links.Net and Netmail.ToNode=Links.Node and Links.NetmailDirect<>0 and Links.LinkType=2 order by Links.LinkID,MessageID", SQL_NTS); if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { GetNetmailMessages(hstmt, hHeap, &NDOQ); } LastAddr.FullAddr=0; hPktFile=INVALID_HANDLE_VALUE; while (NDOQ.First!=NULL) { lpNetmailMessage lpTmp; wsprintfW(LogStr,L"Direct netmail From %u:%u/%u.%u To %u:%u/%u.%u",NDOQ.First->FromAddr.zone,NDOQ.First->FromAddr.net,NDOQ.First->FromAddr.node,NDOQ.First->FromAddr.point,NDOQ.First->ToAddr.zone,NDOQ.First->ToAddr.net,NDOQ.First->ToAddr.node,NDOQ.First->ToAddr.point); AddLogEntry(LogStr); if (LastAddr.FullAddr!=NDOQ.First->ToAddr.FullAddr) { if(LastAddr.FullAddr!=0) { ClosePktFile(hPktFile); CreateDirectoryW(FileboxDirName,NULL); MoveFileExW(tmpFileName,finalPktFileName,MOVEFILE_COPY_ALLOWED); } LastAddr.FullAddr=NDOQ.First->ToAddr.FullAddr; //create file PktNumber=GetPktNumber(hstmt); wsprintfW(FileboxDirName, L"%s\\%u.%u.%u.%u", cfg.FileboxesDir, NDOQ.First->ToAddr.zone, NDOQ.First->ToAddr.net, NDOQ.First->ToAddr.node, NDOQ.First->ToAddr.point); wsprintfW(tmpFileName, L"%s\\%08X.NETMAIL", cfg.TmpOutboundDir, PktNumber); wsprintfW(finalPktFileName,L"%s\\%08X.PKT",FileboxDirName,PktNumber); hPktFile=CreateFileW(tmpFileName,GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_NEW,0,NULL); memset(PktPwd, 0, 9); SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(NDOQ.First->ToAddr.zone), 0, NULL); SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(NDOQ.First->ToAddr.net), 0, NULL); SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(NDOQ.First->ToAddr.node), 0, NULL); SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT, 0, 0, &(NDOQ.First->ToAddr.point), 0, NULL); sqlret = SQLExecDirectW(hstmt, L"Select PktPassword from Links where Zone=? and Net=? and Node=? and Point=?", SQL_NTS); if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { sqlret = SQLFetch(hstmt); if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { SQLGetData(hstmt, 1, SQL_C_CHAR, PktPwd, 9, &cb); } } SQLCloseCursor(hstmt); SQLFreeStmt(hstmt, SQL_RESET_PARAMS); WritePktHeader(hPktFile,&(cfg.MyAddr),&(NDOQ.First->ToAddr),PktPwd); } // WriteNetmailMessage(hPktFile,hHeap,NDOQ.First); // SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&(NDOQ.First->MessageID),0,NULL); sqlret=SQLExecDirectW(hstmt,L"{call sp_NetmailMessageSent(?)}",SQL_NTS); SQLFreeStmt(hstmt,SQL_RESET_PARAMS); // lpTmp=NDOQ.First->NextMsg; HeapFree(hHeap,0,NDOQ.First->MsgText); if (NDOQ.First->ReplyTo!=NULL) HeapFree(hHeap,0,NDOQ.First->ReplyTo); if (NDOQ.First->MsgId!=NULL) HeapFree(hHeap,0,NDOQ.First->MsgId); HeapFree(hHeap,0,NDOQ.First->Subject); HeapFree(hHeap,0,NDOQ.First->ToName); HeapFree(hHeap,0,NDOQ.First->FromName); HeapFree(hHeap,0,NDOQ.First); NDOQ.First=lpTmp; } if (hPktFile!=INVALID_HANDLE_VALUE) { ClosePktFile(hPktFile); CreateDirectoryW(FileboxDirName,NULL); MoveFileExW(tmpFileName,finalPktFileName,MOVEFILE_COPY_ALLOWED); } // EnterCriticalSection(&NetmailRouteCritSect); SQLExecDirectW(hstmt, L"EXECUTE sp_RouteNetmail",SQL_NTS); LeaveCriticalSection(&NetmailRouteCritSect); SetEvent(cfg.hMailerCallGeneratingEvent); //make polls sqlret = SQLExecDirectW(hstmt, L"select Zone,Net,Node from Links,NetmailOutbound,Netmail where Links.LinkID=NetmailOutbound.ToLinkID and Netmail.MessageID=NetmailOutbound.MessageID and Netmail.Locked=0 and Links.DialOut<>0 and Links.LinkType<=2 and Links.Point=0", SQL_NTS); if ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { unsigned short zone, net, node; SQLBindCol(hstmt, 1, SQL_C_USHORT, &zone, 0, NULL); SQLBindCol(hstmt, 2, SQL_C_USHORT, &net, 0, NULL); SQLBindCol(hstmt, 3, SQL_C_USHORT, &node, 0, NULL); sqlret = SQLFetch(hstmt); while ((sqlret == SQL_SUCCESS) || (sqlret == SQL_SUCCESS_WITH_INFO)) { if (zone == cfg.MyAddr.zone) { wsprintfW(LogStr,L"Creating poll to %u:%u/%u", zone, net, node); AddLogEntry(LogStr); swprintf_s(tmpFileName, MAX_PATH, L"%s\\%04hX%04hX.CLO", cfg.BinkOutboundDir, net, node); hPktFile = CreateFileW(tmpFileName, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); CloseHandle(hPktFile); // } sqlret = SQLFetch(hstmt); } SQLCloseCursor(hstmt); SQLFreeStmt(hstmt, SQL_UNBIND); } } } goto loop; threadexit: _InterlockedDecrement(&(cfg.ThreadCount)); SetEvent(cfg.hThreadEndEvent); return 0; }