You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
592 lines
16 KiB
592 lines
16 KiB
#include "pch.hxx"
|
|
#include <imnact.h>
|
|
#include <acctimp.h>
|
|
#include <dllmain.h>
|
|
#include <resource.h>
|
|
#include <nexpress.h>
|
|
#include "newimp.h"
|
|
#include <shlwapi.h>
|
|
#include "strconst.h"
|
|
|
|
ASSERTDATA
|
|
|
|
#define MEMCHUNK 512
|
|
|
|
CNExpressAcctImport::CNExpressAcctImport()
|
|
{
|
|
m_cRef = 1;
|
|
m_fIni = FALSE;
|
|
*m_szIni = 0;
|
|
m_cInfo = 0;
|
|
m_rgInfo = NULL;
|
|
}
|
|
|
|
CNExpressAcctImport::~CNExpressAcctImport()
|
|
{
|
|
if (m_rgInfo != NULL)
|
|
MemFree(m_rgInfo);
|
|
}
|
|
|
|
STDMETHODIMP CNExpressAcctImport::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
if (ppv == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
*ppv = NULL;
|
|
|
|
if ((IID_IUnknown == riid) || (IID_IAccountImport == riid))
|
|
*ppv = (IAccountImport *)this;
|
|
else if (IID_IAccountImport2 == riid)
|
|
*ppv = (IAccountImport2 *)this;
|
|
else
|
|
return(E_NOINTERFACE);
|
|
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CNExpressAcctImport::AddRef()
|
|
{
|
|
return(++m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CNExpressAcctImport::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return(0);
|
|
}
|
|
|
|
return(m_cRef);
|
|
}
|
|
|
|
const static char c_szConfig[] = "Config";
|
|
const static char c_szAuth[] = "Auth";
|
|
const static char c_szNxNNTPServer[] = "NNTPServer";
|
|
const static char c_szFullname[] = "Fullname";
|
|
const static char c_szOrganization[] = "Organization";
|
|
const static char c_szEmail[] = "Email";
|
|
const static char c_szNxUsername[] = "Username";
|
|
const static char c_szNNTPPort[] = "NNTPPort";
|
|
const static char c_szHomeDir[] = "HomeDir";
|
|
const static char c_szNewsrc[] = "NewsRC";
|
|
const static char c_szNxIni[] = "\\nx.ini";
|
|
const static char c_szNx[] = "nx";
|
|
|
|
const static char c_szRegServicesDef[] = "Software\\NewsXpress\\Services\\Default";
|
|
const static char c_szRegAuth[] = "Software\\NewsXpress\\Services\\Default\\Authorization";
|
|
const static char c_szRegNxUser[] = "Software\\NewsXpress\\User";
|
|
const static char c_szRegNxRoot[] = "Software\\NewsXpress";
|
|
const static char c_szRegNNTPServer[] = "NNTP Server";
|
|
const static char c_szRegNNTPPort[] = "NNTP Port";
|
|
const static char c_szRegHomeDir[] = "Home Dir";
|
|
|
|
HRESULT STDMETHODCALLTYPE CNExpressAcctImport::AutoDetect(DWORD *pcAcct, DWORD dwFlags)
|
|
{
|
|
HKEY hkey;
|
|
DWORD type, cb, dw;
|
|
char szNewsServer[MAX_PATH], szWinPath[MAX_PATH];
|
|
|
|
Assert(m_cInfo == 0);
|
|
|
|
if (pcAcct == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
*pcAcct = 0;
|
|
|
|
cb = sizeof(szNewsServer);
|
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegServicesDef, c_szRegNNTPServer, &type, (LPBYTE)szNewsServer, &cb))
|
|
{
|
|
if (!MemAlloc((void **)&m_rgInfo, sizeof(NXACCTINFO)))
|
|
return(E_OUTOFMEMORY);
|
|
m_rgInfo->dwCookie = 0;
|
|
*m_rgInfo->szUserPath = 0;
|
|
StrCpyN(m_rgInfo->szDisplay, szNewsServer, ARRAYSIZE(m_rgInfo->szDisplay));
|
|
m_cInfo = 1;
|
|
}
|
|
else
|
|
{
|
|
if (0 == GetEnvironmentVariable(c_szNx, szWinPath, ARRAYSIZE(szWinPath)))
|
|
{
|
|
if (0 == GetWindowsDirectory(szWinPath, ARRAYSIZE(szWinPath)))
|
|
return(S_OK);
|
|
|
|
StrCatBuff(szWinPath, c_szNxIni, ARRAYSIZE(szWinPath));
|
|
}
|
|
|
|
dw = GetFileAttributes(szWinPath);
|
|
if (dw != -1 && dw != FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (GetPrivateProfileString(c_szConfig, c_szNxNNTPServer, c_szEmpty, szNewsServer, ARRAYSIZE(szNewsServer), szWinPath))
|
|
{
|
|
if (!MemAlloc((void **)&m_rgInfo, sizeof(NXACCTINFO)))
|
|
return(E_OUTOFMEMORY);
|
|
m_rgInfo->dwCookie = 0;
|
|
StrCpyN(m_rgInfo->szUserPath, szWinPath, ARRAYSIZE(m_rgInfo->szUserPath));
|
|
StrCpyN(m_rgInfo->szDisplay, szNewsServer, ARRAYSIZE(m_rgInfo->szDisplay));
|
|
m_cInfo = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pcAcct = m_cInfo;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CNExpressAcctImport::InitializeImport(HWND hwnd, DWORD_PTR dwCookie)
|
|
{
|
|
Assert(dwCookie == 0);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CNExpressAcctImport::EnumerateAccounts(IEnumIMPACCOUNTS **ppEnum)
|
|
{
|
|
CEnumNXACCT *penum;
|
|
HRESULT hr;
|
|
|
|
if (ppEnum == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
*ppEnum = NULL;
|
|
|
|
if (m_cInfo == 0)
|
|
return(S_FALSE);
|
|
Assert(m_rgInfo != NULL);
|
|
|
|
penum = new CEnumNXACCT;
|
|
if (penum == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
hr = penum->Init(m_rgInfo, m_cInfo);
|
|
if (FAILED(hr))
|
|
{
|
|
penum->Release();
|
|
penum = NULL;
|
|
}
|
|
|
|
*ppEnum = penum;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CNExpressAcctImport::GetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (pAcct == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
hr = IGetSettings(dwCookie, pAcct, NULL);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CNExpressAcctImport::IGetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey;
|
|
UINT port;
|
|
NXACCTINFO *pinfo;
|
|
char sz[512];
|
|
DWORD cb, type;
|
|
|
|
Assert(((int) dwCookie) >= 0 && dwCookie < (DWORD_PTR)m_cInfo);
|
|
pinfo = &m_rgInfo[dwCookie];
|
|
|
|
Assert(pinfo->dwCookie == dwCookie);
|
|
|
|
hr = pAcct->SetPropSz(AP_ACCOUNT_NAME, pinfo->szDisplay);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (*pinfo->szUserPath != 0)
|
|
{
|
|
// ini file
|
|
|
|
if (GetPrivateProfileString(c_szConfig, c_szNxNNTPServer, c_szEmpty, sz, ARRAYSIZE(sz), pinfo->szUserPath))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_SERVER, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
port = GetPrivateProfileInt(c_szConfig, c_szNNTPPort, 0, pinfo->szUserPath);
|
|
if (port != 0)
|
|
{
|
|
hr = pAcct->SetPropDw(AP_NNTP_PORT, port);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
if (GetPrivateProfileString(c_szConfig, c_szFullname, c_szEmpty, sz, ARRAYSIZE(sz), pinfo->szUserPath))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_DISPLAY_NAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
if (GetPrivateProfileString(c_szConfig, c_szEmail, c_szEmpty, sz, ARRAYSIZE(sz), pinfo->szUserPath))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_EMAIL_ADDRESS, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
if (GetPrivateProfileString(c_szConfig, c_szOrganization, c_szEmpty, sz, ARRAYSIZE(sz), pinfo->szUserPath))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_ORG_NAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
if (GetPrivateProfileString(c_szAuth, c_szNxUsername, c_szEmpty, sz, ARRAYSIZE(sz), pinfo->szUserPath))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_USERNAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// registry
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegServicesDef, 0, KEY_READ, &hkey))
|
|
{
|
|
cb = sizeof(sz);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegNNTPServer, NULL, &type, (LPBYTE)sz, &cb))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_SERVER, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
cb = sizeof(port);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegNNTPPort, NULL, &type, (LPBYTE)&port, &cb) && port != 0)
|
|
{
|
|
hr = pAcct->SetPropDw(AP_NNTP_PORT, port);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
cb = sizeof(sz);
|
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegAuth, c_szNxUsername, &type, (LPBYTE)sz, &cb) && cb > 1)
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_USERNAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegNxUser, 0, KEY_READ, &hkey))
|
|
{
|
|
cb = sizeof(sz);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szEmail, NULL, &type, (LPBYTE)sz, &cb))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_EMAIL_ADDRESS, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
cb = sizeof(sz);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szFullname, NULL, &type, (LPBYTE)sz, &cb))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_DISPLAY_NAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
cb = sizeof(sz);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szOrganization, NULL, &type, (LPBYTE)sz, &cb))
|
|
{
|
|
hr = pAcct->SetPropSz(AP_NNTP_ORG_NAME, sz);
|
|
Assert(!FAILED(hr));
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
}
|
|
|
|
if (pInfo != NULL)
|
|
{
|
|
// TODO: can we do any better than this???
|
|
pInfo->dwConnect = CONN_USE_DEFAULT;
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CNExpressAcctImport::GetNewsGroup(INewsGroupImport *pImp, DWORD dwReserved)
|
|
{
|
|
BOOL fRet;
|
|
DWORD cb, type;
|
|
char szHomeDir[MAX_PATH], szRCFile[MAX_PATH];
|
|
HRESULT hr = S_OK;
|
|
char *pListGroups = NULL;
|
|
|
|
Assert(pImp != NULL);
|
|
|
|
*szHomeDir = 0;
|
|
fRet = FALSE;
|
|
|
|
if (*m_rgInfo->szUserPath != 0)
|
|
{
|
|
if (GetPrivateProfileString(c_szConfig, c_szHomeDir, c_szEmpty, szHomeDir, MAX_PATH, m_rgInfo->szUserPath) &&
|
|
GetPrivateProfileString(c_szConfig, c_szNewsrc, c_szEmpty, szRCFile, MAX_PATH, m_rgInfo->szUserPath))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cb = sizeof(szHomeDir);
|
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegNxRoot, c_szRegHomeDir, &type, (LPBYTE)szHomeDir, &cb) && cb > 1)
|
|
{
|
|
cb = sizeof(szRCFile);
|
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegServicesDef, c_szNewsrc, &type, (LPBYTE)szRCFile, &cb) && cb > 1)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fRet)
|
|
{
|
|
PathAppend(szHomeDir, szRCFile);
|
|
|
|
if (SUCCEEDED(hr = GetSubListGroups(szHomeDir, &pListGroups)))
|
|
{
|
|
hr = pImp->ImportSubList(pListGroups);
|
|
|
|
MemFree(pListGroups);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNExpressAcctImport::GetSubListGroups(char *szHomeDir, char **ppListGroups)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hRCHandle = NULL;
|
|
HANDLE hRCFile = NULL;
|
|
ULONG cbRCFile = 0;
|
|
BYTE *pBegin = NULL,
|
|
*pCurr = NULL,
|
|
*pEnd = NULL;
|
|
int nBalMem = MEMCHUNK;
|
|
int nLine = 0,
|
|
nCount = 0;
|
|
char cPlaceHolder = 1;
|
|
char szLineHolder[MEMCHUNK];
|
|
char *pListGroups = NULL;
|
|
|
|
Assert(szHomeDir);
|
|
Assert(ppListGroups);
|
|
*ppListGroups = NULL;
|
|
|
|
hRCHandle = CreateFile( szHomeDir, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
|
|
if(hRCHandle == INVALID_HANDLE_VALUE)
|
|
return hr;
|
|
|
|
cbRCFile = GetFileSize(hRCHandle, NULL);
|
|
|
|
if(!cbRCFile) // Empty File.
|
|
goto Done;
|
|
|
|
hRCFile = CreateFileMapping(hRCHandle, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
|
|
if(hRCFile == NULL)
|
|
{
|
|
CloseHandle(hRCHandle);
|
|
return hr;
|
|
}
|
|
|
|
pBegin = (BYTE *)MapViewOfFile( hRCFile, FILE_MAP_READ, 0, 0, 0);
|
|
|
|
if(pBegin == NULL)
|
|
{
|
|
CloseHandle(hRCHandle);
|
|
CloseHandle(hRCFile);
|
|
return hr;
|
|
}
|
|
|
|
pCurr = pBegin;
|
|
pEnd = pCurr + cbRCFile;
|
|
|
|
if (!MemAlloc((void **)&pListGroups, MEMCHUNK))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
DWORD cchSizeListGroups = MEMCHUNK;
|
|
ZeroMemory((void*)pListGroups, (cchSizeListGroups * sizeof(pListGroups[0])));
|
|
|
|
while (pCurr < pEnd)
|
|
{
|
|
nLine = 0;
|
|
while(!((pCurr[nLine] == ':') || (pCurr[nLine] == '!')) && (pCurr + nLine < pEnd))
|
|
nLine++;
|
|
|
|
if(pCurr + nLine > pEnd)
|
|
break;
|
|
|
|
if(pCurr[nLine] == '!')
|
|
goto LineEnd;
|
|
|
|
nLine++;
|
|
if(nLine < MEMCHUNK)
|
|
StrCpyN(szLineHolder, (char*)pCurr, nLine);
|
|
else
|
|
continue;
|
|
|
|
if(nLine + 2 < nBalMem)
|
|
{
|
|
StrCatBuff(pListGroups, szLineHolder, cchSizeListGroups);
|
|
StrCatBuff(pListGroups, "\1", cchSizeListGroups);
|
|
nBalMem -= (nLine + 2);
|
|
}
|
|
else
|
|
{
|
|
cchSizeListGroups += (lstrlen(pListGroups) + 1 + MEMCHUNK);
|
|
if(!MemRealloc((void **)&pListGroups, (cchSizeListGroups * sizeof(pListGroups[0]))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Done;
|
|
}
|
|
nBalMem += MEMCHUNK;
|
|
StrCatBuff(pListGroups, szLineHolder, cchSizeListGroups);
|
|
StrCatBuff(pListGroups, "\1", cchSizeListGroups);
|
|
nBalMem -= (nLine + 2);
|
|
}
|
|
|
|
LineEnd:
|
|
while(!((pCurr[nLine] == 0x0D) && (pCurr[nLine + 1] == 0x0A)) && (pCurr + nLine < pEnd))
|
|
nLine++;
|
|
pCurr += (nLine + 2);
|
|
}
|
|
|
|
if(lstrlen(pListGroups))
|
|
{
|
|
while(pListGroups[nCount] != '\0')
|
|
{
|
|
if(pListGroups[nCount] == cPlaceHolder)
|
|
{
|
|
pListGroups[nCount] = '\0';
|
|
}
|
|
nCount++;
|
|
}
|
|
*ppListGroups = pListGroups;
|
|
hr = S_OK;
|
|
}
|
|
|
|
Done:
|
|
if(hRCHandle != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hRCHandle);
|
|
if(pBegin)
|
|
UnmapViewOfFile(pBegin);
|
|
if(hRCFile)
|
|
CloseHandle(hRCFile);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CNExpressAcctImport::GetSettings2(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo)
|
|
{
|
|
if (pAcct == NULL ||
|
|
pInfo == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
return(IGetSettings(dwCookie, pAcct, pInfo));
|
|
}
|
|
|
|
CEnumNXACCT::CEnumNXACCT()
|
|
{
|
|
m_cRef = 1;
|
|
// m_iInfo
|
|
m_cInfo = 0;
|
|
m_rgInfo = NULL;
|
|
}
|
|
|
|
CEnumNXACCT::~CEnumNXACCT()
|
|
{
|
|
if (m_rgInfo != NULL)
|
|
MemFree(m_rgInfo);
|
|
}
|
|
|
|
STDMETHODIMP CEnumNXACCT::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
|
|
if (ppv == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IID_IUnknown == riid)
|
|
*ppv = (IUnknown *)this;
|
|
else if (IID_IEnumIMPACCOUNTS == riid)
|
|
*ppv = (IEnumIMPACCOUNTS *)this;
|
|
|
|
if (*ppv != NULL)
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
else
|
|
return(E_NOINTERFACE);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CEnumNXACCT::AddRef()
|
|
{
|
|
return(++m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CEnumNXACCT::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return(0);
|
|
}
|
|
|
|
return(m_cRef);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CEnumNXACCT::Next(IMPACCOUNTINFO *pinfo)
|
|
{
|
|
if (pinfo == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
m_iInfo++;
|
|
if ((UINT)m_iInfo >= m_cInfo)
|
|
return(S_FALSE);
|
|
|
|
Assert(m_rgInfo != NULL);
|
|
|
|
pinfo->dwCookie = m_rgInfo[m_iInfo].dwCookie;
|
|
pinfo->dwReserved = 0;
|
|
StrCpyN(pinfo->szDisplay, m_rgInfo[m_iInfo].szDisplay, ARRAYSIZE(pinfo->szDisplay));
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CEnumNXACCT::Reset()
|
|
{
|
|
m_iInfo = -1;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CEnumNXACCT::Init(NXACCTINFO *pinfo, int cinfo)
|
|
{
|
|
DWORD cb;
|
|
|
|
Assert(pinfo != NULL);
|
|
Assert(cinfo > 0);
|
|
|
|
cb = cinfo * sizeof(NXACCTINFO);
|
|
|
|
if (!MemAlloc((void **)&m_rgInfo, cb))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
m_iInfo = -1;
|
|
m_cInfo = cinfo;
|
|
CopyMemory(m_rgInfo, pinfo, cb);
|
|
|
|
return(S_OK);
|
|
}
|