Re: ATL shell extension calls an ATL COM object but crashes after
Correct, the authenticate method is implemented in a separate dll. The
"authenticate" method below is the public method defined in the interface. It
just calls a web service (RPC) over HTTPS to authenticate the user.
STDMETHODIMP CMyUploadObj::authenticate(BSTR* env)
{
_bstr_t prodUrl = "https://www.dot.com/webservices/AuthService";
string prodEnv = "PROD";
_bstr_t testUrl = "https://www.dot.com/webservices/AuthService";
string testEnv = "TEST";
_bstr_t devUrl = "https://www.dot.com/webservices/AuthService";
string devEnv = "DEV";
_bstr_t envTemp = *env;
string envStr = envTemp;
_bstr_t authurl("");
if(prodEnv.compare(envStr) == 0)
{
authurl = prodUrl;
}
else if(testEnv.compare(envStr) == 0)
{
authurl = testUrl;
}
else
{
authurl = devUrl;
}
m_bstrUserAgent = "PostUploadObj";
HINTERNET hOpen = NULL, hConnect = NULL, hReq;
hReq = getRequest(authurl, hOpen, hConnect);
if(hReq == NULL)
{
return S_OK;
}
if(!authenticateWS(hReq))
{
closeHandles(hOpen, hConnect, hReq);
return S_OK;
}
closeHandles(hOpen, hConnect, hReq);
return S_OK;
}
HINTERNET CMyUploadObj::getRequest(_bstr_t url, HINTERNET hOpen, HINTERNET
hConnect)
{
HINTERNET hReq;
DWORD dwFlags = INTERNET_FLAG_RELOAD |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_KEEP_CONNECTION;
INTERNET_PORT dwPort;
LPSTR AcceptTypes[2] = {"*/*", NULL};
m_bstrMethod = "POST";
m_bstrErrorMsg = "Success";
string strUrl;
string host;
string postAcceptor;
if ( !(hOpen = InternetOpen ( m_bstrUserAgent,
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0) ) )
{
m_bstrErrorMsg = "InternetOpen Failed";
closeHandles(hOpen, NULL, NULL);
return NULL;
}
// SSL upload url
dwPort = INTERNET_DEFAULT_HTTPS_PORT;
dwFlags |= INTERNET_FLAG_SECURE;
strUrl = url;
size_t protocolLen = 7;
size_t hostStart = protocolLen + 1;
size_t hostLen = strUrl.find(".com") + 4 - hostStart;
size_t postAcceptorStart = hostLen + hostStart;
host = strUrl.substr(hostStart, hostLen);
postAcceptor = strUrl.substr(postAcceptorStart);
m_bstrHost = host.c_str();
if ( !(hConnect = InternetConnect( hOpen, m_bstrHost, dwPort, NULL, NULL,
INTERNET_SERVICE_HTTP, 0, 0) ))
{
m_bstrErrorMsg = "InternetConnect Failed";
closeHandles(hOpen, hConnect, NULL);
return NULL;
}
m_bstrPostAcceptor = postAcceptor.c_str();
if ( !(hReq = HttpOpenRequest (hConnect, m_bstrMethod, m_bstrPostAcceptor,
HTTP_VERSION, NULL,
(LPCTSTR*) AcceptTypes, dwFlags ,0 ) ))
{
m_bstrErrorMsg = "HttpOpenRequest Failed";
closeHandles(hOpen, hConnect, hReq);
return NULL;
}
return hReq;
}
void CMyUploadObj::closeHandles(HINTERNET hOpen, HINTERNET hConnect,
HINTERNET hReq)
{
if(hOpen) InternetCloseHandle(hOpen);
if(hConnect) InternetCloseHandle(hConnect);
if(hReq) InternetCloseHandle(hReq);
}
bool CMyUploadObj::authenticateWS(HINTERNET hRequest)
{
_bstr_t sHeader("Content-Type: text/xml");
sHeader += ("\r\nSOAPAction: Auth");
sHeader += "\r\n";
DWORD dwError = 0;
if(HttpAddRequestHeaders(hRequest, sHeader, -1, 0))
{
_bstr_t sPayload = get_payload();
INTERNET_BUFFERS InBuf;
ZeroMemory(&InBuf, sizeof(INTERNET_BUFFERS));
InBuf.dwStructSize = sizeof(INTERNET_BUFFERS);
InBuf.dwBufferTotal = sPayload.length();
again:
BOOL retval = HttpSendRequestEx(hRequest, &InBuf, NULL, 0, 0);
if(retval)
{
unsigned long ulWrote;
BOOL bWrote;
BOOL bRead;
bWrote = InternetWriteFile(hRequest, (const void*)(const char*)sPayload,
sPayload.length(), &ulWrote);
bWrote &= HttpEndRequest(hRequest, NULL, 0, 0);
if(!bWrote)
{
dwError = GetLastError();
{
if(ERROR_INTERNET_FORCE_RETRY == dwError)
goto again;
else
{
m_bstrErrorMsg = "HttpEndRequest Failed";
return false;
}
}
}
CHAR szBuffer[2048] = "\0";
DWORD dwBytesRead;
bRead = InternetReadFile(hRequest, szBuffer, 2048, &dwBytesRead);
if(!bRead)
{
m_bstrErrorMsg = "InternetReadFile Failed";
return false;
}
else
{
string successMsg = "true";
string failureMsg = "false";
string authReturn;
authReturn = (const char *)szBuffer;
size_t successStart = authReturn.find("<success
xsi:type=\"xsd:boolean\">") + 32;
size_t successEnd = authReturn.find("</success>");
string returnCode =authReturn.substr(successStart, successEnd -
successStart);
if(successMsg.compare(returnCode) != 0)
{
m_bstrErrorMsg = "Failure on Authenticate";
return false;
}
else
{
setAuthUrl(authReturn);
}
}
}
else
{
m_bstrErrorMsg = "HttpSendRequestEx Failed";
dwError = GetLastError();
return false;
}
}
else
{
m_bstrErrorMsg = "HttpAddRequestHeaders Failed";
return false;
}
return true;
}
_bstr_t CMyUploadObj::get_payload()
{
_bstr_t payload("<?xml version=\"1.0\" encoding=\"utf-8\"?> ");
payload += ("<soap:Envelope
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
payload += ("xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"
");
payload += ("xmlns:tns=\"http://www.dot.com/webservices/AuthService\" ");
payload +=
("xmlns:types=\"http://www.dot.com/webservices/AuthService/encodedTypes\" ");
payload += ("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
payload += ("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> ");
payload += ("<soap:Body
soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"> ");
payload += ("<q1:authenticate xmlns:q1=\"http://webservice.dot.com\"> ");
payload += ("<userId xsi:type=\"xsd:long\">abc</userId> ");
payload += ("<password xsi:type=\"xsd:string\">abcdef</password> ");
payload += ("</q1:authenticate> ");
payload += ("</soap:Body> ");
payload += ("</soap:Envelope>");
return payload;
}
"SvenC" wrote:
Hi TexMags wrote,
I assume you mean the .tlh file I have inside my project? Let me know
if it's something else that you mean.
virtual HRESULT __stdcall raw_authenticate (
/*[in]*/ BSTR * env ) = 0;
CComBSTR cbstrAuthEnv = "env1";
CoInitialize(NULL);
MyUploadLib::IMyUploadObjPtr upload;
upload.CreateInstance(__uuidof(MyUploadLib::MyUploadObj));
upload->authenticate(&cbstrAuthEnv);
OK, the above header fits your call.
Do you implement the MyUpload component?
If yes, please show the code for authenticate.
--
SvenC