Ejemplo n.º 1
0
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);
    }
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
__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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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;
}