I'm trying to send multipart/form-data using httpsendrequest in c++ but it doesn't seem to work. I'm using the RFC standard for boundary and this is the code I have. I'm sending simple data, plain but trying to use multipart/form-data so I can understand how boundaries work but it doesn't send. This is the code that I've got so far.
#define _WIN32_WINNT 0x600
#include <stdio.h>
#include <wininet.h>
#define BUFLEN 1024
static LPCTSTR acceptTypes[] = {"*/*", NULL};
static const char *postData = "submit=submit&cool=hawk";
static char headers[] = TEXT("Content-Type: multipart/form-data; boundary=abcde\r\n"
"--abcde\r\n"
"Content-Disposition: form-data; name=\"cool\"\r\n"
"testval\r\n"
"--abcde\r\n");
int main()
{
HINTERNET hSession, hConnect, hFile;
if( ( hSession = InternetOpen(
"myapp",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0
) ) == NULL )
{
printf("Couldn't start session. Error %ld\n", GetLastError());
exit(1);
}
printf("Session started\n");
if( ( hConnect = InternetConnect(
hSession,
"localhost",
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
0
) ) == NULL )
{
printf("Unable to connect to server. Error %ld\n", GetLastError());
exit(1);
}
printf("Connected to server\n");
if( ( hFile = HttpOpenRequest(
hConnect,
"POST",
"/test/index.php",
NULL,
NULL,
acceptTypes,
INTERNET_FLAG_RELOAD,
0
) ) == NULL )
{
printf("Unable to open request. Error %ld\n", GetLastError());
exit(1);
}
printf("Opening request..Opened\n");
unsigned long dataLen = strlen(postData)+1;
bool res = HttpSendRequest(
hFile,
headers,
-1,
(char*)postData,
dataLen
);
if( !res )
{
printf("Unable to send request. Error %ld\n", GetLastError());
exit(1);
}
printf("Request sent\n");
// char *szBuffer = (char*)malloc(sizeof(char)*BUFLEN);
char szBuffer[BUFLEN];
DWORD dwRead = 0;
memset(&szBuffer, '\0', sizeof(szBuffer));
while( InternetReadFile(hFile, szBuffer, sizeof(szBuffer), &dwRead) && dwRead )
{
printf("%s", szBuffer);
}
return 0;
}
Related
I wrote this code to encrypt a file in python with AES and now I send this file over HTTP to a client in C++ using Windows OS. And I want to decrypt this file on the C++ client, but I haven't found any libraries/usefull code to help me with this manner.
Here is the code for python:
def derive_key_and_iv(password, salt, key_length, iv_length):
d = d_i = b''
while len(d) < key_length + iv_length:
d_i = md5(d_i + str.encode(password) + salt).digest()
d += d_i
return d[:key_length], d[key_length:key_length + iv_length]
def encrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size # 16 bytes
salt = urandom(bs)
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
out_file.write(salt)
finished = False
while not finished:
chunk = in_file.read(1024 * bs)
if len(chunk) == 0 or len(chunk) % bs != 0: #final block
padding_length = (bs - len(chunk) % bs) or bs
chunk += str.encode(padding_length * chr(padding_length))
finished = True
out_file.write(cipher.encrypt(chunk))
password = 'ABCDE' # some password
with open("some_file.bin", "rb") as in_file, open("enc_some_file.enc", "wb") as out_file:
encrypt(in_file, out_file, password)
Update:
I am updating this question regarding my try with WinCrypt. I am trying to compile from VS CODE using MSYS64 g++ compiler on Windows. Here is the code that I am trying to run. I also have some additional libraries to help me with the client-server part, such as libcurlpp and libcurl.
#include <string>
#include <sstream>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <wincrypt.h>
#include <windows.h>
#define AES_KEY_SIZE 32
#define IN_CHUNK_SIZE (AES_KEY_SIZE * 10) // a buffer must be a multiple of the key size
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2) // an output buffer (for encryption) must be twice as big
using namespace std;
string host = ""; #some host
int main(void)
{
curlpp::Easy req;
req.setOpt(new curlpp::options::Url(host));
ofstream myfile;
myfile.open("enc_calc.enc", ios::out | ios::binary);
myfile << req;
myfile.close();
getch();
wchar_t *in_file = (wchar_t *)"enc_calc.enc";
wchar_t *out_file = (wchar_t *)"calc.dll";
wchar_t default_key[] = L"ABCDE";
wchar_t *key_str = default_key;
const size_t len = lstrlenW(key_str);
const size_t key_size = len * sizeof(key_str[0]);
const wchar_t *filename1 = (const wchar_t *)"enc_calc.enc";
const wchar_t *filename2 = (const wchar_t *)"calc.dll";
HANDLE hInpFile = CreateFileW(filename1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hInpFile == INVALID_HANDLE_VALUE) {
printf("Cannot open input file!\n");
system("pause");
return (-1);
}
HANDLE hOutFile = CreateFileW(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutFile == INVALID_HANDLE_VALUE) {
printf("Cannot open output file!\n");
system("pause");
return (-1);
}
DWORD dwStatus = 0;
BOOL bResult = FALSE;
wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider";
HCRYPTPROV hProv;
if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
dwStatus = GetLastError();
printf("CryptCreateHash failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
if (!CryptHashData(hHash, (BYTE*)key_str, key_size, 0)) {
DWORD err = GetLastError();
printf("CryptHashData Failed : %#x\n", err);
system("pause");
return (-1);
}
printf("[+] CryptHashData Success\n");
HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) {
dwStatus = GetLastError();
printf("CryptDeriveKey failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
printf("[+] CryptDeriveKey Success\n");
const size_t chunk_size = IN_CHUNK_SIZE;
BYTE *chunk = new BYTE[chunk_size];
DWORD out_len = 0;
BOOL isFinal = FALSE;
DWORD readTotalSize = 0;
DWORD inputSize = GetFileSize(hInpFile, NULL);
while (bResult = ReadFile(hInpFile, chunk, IN_CHUNK_SIZE, &out_len, NULL)) {
if (0 == out_len) {
break;
}
readTotalSize += out_len;
if (readTotalSize >= inputSize) {
isFinal = TRUE;
printf("Final chunk set, len: %d = %x\n", out_len, out_len);
}
if (!CryptDecrypt(hKey, NULL, isFinal, 0, chunk, &out_len)) {
printf("[-] CryptDecrypt failed: %x\n", GetLastError());
break;
}
DWORD written = 0;
if (!WriteFile(hOutFile, chunk, out_len, &written, NULL)) {
printf("writing failed!\n");
break;
}
memset(chunk, 0, chunk_size);
}
delete[]chunk; chunk = NULL;
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);
CryptReleaseContext(hProv, 0);
CloseHandle(hInpFile);
CloseHandle(hOutFile);
printf("Finished. Processed %#x bytes.\n", readTotalSize);
return 0;
}
The errors I'm getting are regarding the windows.h library, such as:
"ULONG does not name a type" and other types in windows. and at runtime: "Cannot Open input file", not sure why, even tho the file is downloaded in the current folder and I'm trying to open it as such in the code.
I'm currently trying to write a class to make sending simple requests easier for me.
In the end I'd like it to be usable somewhat like this:
int _tmain(int argc, _TCHAR* argv[])
{
HttpRequest Request(L"Example UserAgent/1.0",L"",L"");
Request.SendRequest(L"google.com",L"GET",NULL);
if (Request.responseHeader)
printf("%s",Request.responseHeader);
if (Request.responseBody)
printf("%s",Request.responseBody);
getchar();
return 0;
}
But for now it doesn't work at all. I have no idea how I could get the response header and I'm failing writing the response header to a public member of my class.
Yeah I'm really bad at C++ especially when it's about the winapi.
Well I hope you can help me out.
Here is my code so far:
#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
class HttpRequest {
private:
DWORD dwSize;
DWORD dwDownloaded;
LPSTR pszOutBuffer;
BOOL bResults;
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
LPCWSTR _userAgent;
//LPCWSTR _proxyIp;
//LPCWSTR _proxyPort;
size_t bodySize;
public:
HttpRequest(LPCWSTR, LPCWSTR, LPCWSTR);
void SendRequest(LPCWSTR, LPCWSTR, LPVOID);
LPSTR responseHeader[1000000];
LPSTR responseBody[1000000];
};
HttpRequest::HttpRequest(LPCWSTR userAgent, LPCWSTR proxyIp, LPCWSTR proxyPort) {
_userAgent = userAgent;
//_proxyIp = proxyIp;
//_proxyPort = proxyPort;
hSession = WinHttpOpen( userAgent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
}
void HttpRequest::SendRequest(LPCWSTR url, LPCWSTR method, LPVOID body) {
bodySize = 0;
if (hSession)
hConnect = WinHttpConnect( hSession, url, INTERNET_DEFAULT_HTTPS_PORT, 0 );
else
printf("session handle failed\n");
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, method, NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
else
printf("connect handle failed\n");
if (hRequest)
bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, 0, 0, 0 );
else
printf("request handle failed\n");
if( bResults )
bResults = WinHttpReceiveResponse( hRequest, NULL );
if( bResults )
{
do
{
// Check for available data.
dwSize = 0;
if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
printf( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) );
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize+1];
if( !pszOutBuffer )
{
printf( "Out of memory\n" );
dwSize=0;
}
else
{
// Read the data.
ZeroMemory( pszOutBuffer, dwSize+1 );
if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded ) )
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
else {
//printf( "%s", pszOutBuffer );
responseBody[bodySize++] = pszOutBuffer;
}
// Free the memory allocated to the buffer.
delete [] pszOutBuffer;
}
} while( dwSize > 0 );
}
// Report any errors.
if( !bResults )
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
}
Use WinHttpQueryHeaders() to access the response headers. Use the WINHTTP_QUERY_RAW_HEADERS(_CRLF) flag to specify that you want to retrieve all of the available headers.
You also need to change your class to dynamically allocate its responseHeader and responseBody members. You are wasting a lot of memory, as well as limiting the response size you can handle, by using static arrays.
Try this:
#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <vector>
#pragma comment(lib, "winhttp.lib")
class HttpRequest
{
private:
std::wstring _userAgent;
//std::wstring _proxyIp;
//std::wstring _proxyPort;
public:
HttpRequest(const std::wstring&, const std::wstring&, const std::wstring&);
bool SendRequest(const std::wstring&, const std::wstring&, void*, DWORD);
std::wstring responseHeader;
std::vector<BYTE> responseBody;
};
HttpRequest::HttpRequest(const std::wstring &userAgent, const std::wstring &proxyIp, const std::wstring &proxyPort) :
_userAgent(userAgent)
//,_proxyIp(proxyIp)
//,_proxyPort(proxyPort)
{
}
bool HttpRequest::SendRequest(const std::wstring &url, const std::wstring &method, void *body, DWORD bodySize)
{
DWORD dwSize;
DWORD dwDownloaded;
DWORD headerSize = 0;
BOOL bResults = FALSE;
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
responseHeader.resize(0);
responseBody.resize(0);
hSession = WinHttpOpen( _userAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
if (hSession)
hConnect = WinHttpConnect( hSession, url.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0 );
else
printf("session handle failed\n");
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, method.c_str(), NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
else
printf("connect handle failed\n");
if (hRequest)
bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, bodySize, 0, 0 );
else
printf("request handle failed\n");
if (bResults)
bResults = WinHttpReceiveResponse( hRequest, NULL );
if (bResults)
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, WINHTTP_NO_OUTPUT_BUFFER, &headerSize, WINHTTP_NO_HEADER_INDEX);
if ((!bResults) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
responseHeader.resize(headerSize / sizeof(wchar_t));
if (responseHeader.empty())
{
bResults = TRUE;
}
else
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, &responseHeader[0], &headerSize, WINHTTP_NO_HEADER_INDEX);
if( !bResults ) headerSize = 0;
responseHeader.resize(headerSize / sizeof(wchar_t));
}
}
}
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
bResults = WinHttpQueryDataAvailable( hRequest, &dwSize );
if (!bResults)
{
printf( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) );
break;
}
if (dwSize == 0)
break;
do
{
// Allocate space for the buffer.
DWORD dwOffset = responseBody.size();
responseBody.resize(dwOffset+dwSize);
// Read the data.
bResults = WinHttpReadData( hRequest, &responseBody[dwOffset], dwSize, &dwDownloaded );
if (!bResults)
{
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
dwDownloaded = 0;
}
responseBody.resize(dwOffset+dwDownloaded);
if (dwDownloaded == 0)
break;
dwSize -= dwDownloaded;
}
while (dwSize > 0);
}
while (true);
}
// Report any errors.
if (!bResults)
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
return bResults;
}
int _tmain(int argc, _TCHAR* argv[])
{
HttpRequest Request(L"Example UserAgent/1.0",L"",L"");
if (Request.SendRequest(L"google.com",L"GET",NULL,0))
{
printf("%ls",Request.responseHeader.c_str());
if (!Request.responseBody.empty())
printf("%*s",Request.responseBody.size(),(char*)&Request.responseBody[0]);
}
getchar();
return 0;
}
I have been trying this the whole day but no luck i want to upload an image file to a php file which i have created but when ever i try to do that winhttpsendrequest throws 183 error that means cannot send file that is already sent please can someone point out where i am wrong
c++ code:
int _tmain(int argc, _TCHAR* argv[]) {
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
BOOL bResults = FALSE;
FILE *pFile;
long lSize;
char *buffer;
size_t result;
pFile = fopen("blog.jpg", "rb");
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
buffer = (char *) malloc(sizeof(char) * lSize);
result = fread(buffer, 1, lSize, pFile);
fclose(pFile);
hSession = WinHttpOpen( L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
if (hSession)
hConnect = WinHttpConnect(hSession, L"localhost",
INTERNET_DEFAULT_HTTP_PORT, 0);
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", L"locker/upload.php",
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH);
static WCHAR frmdata[2048] = L"Connection: keep-alive\r\nContent-Type: multipart/form-data; -----------------------------7d82751e2bc0858\r\nContent-Disposition: form-data; name=\"file\"; filename=\"blog.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
bResults = WinHttpSendRequest(hRequest,
frmdata, wcslen(frmdata), buffer,
lSize, wcslen(frmdata)+lSize, 0);
if (bResults) {
/*
DWORD dwBytesWritten = 0;
bResults = WinHttpWriteData(hRequest, buffer,
lSize,
&dwBytesWritten);
if (bResults) {
printf_s("Data: %d", dwBytesWritten);
}
*/
} else {
printf_s("SendReq: %d", GetLastError());
}
free(buffer);
if (hRequest) { WinHttpCloseHandle(hRequest); }
if (hConnect) { WinHttpCloseHandle(hConnect); }
if (hSession) { WinHttpCloseHandle(hSession); }
getchar();
return 0;
}
php code:
if (isset($_FILES["file"])) {
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['file']['name']). " has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
Keshav Nair.
try to this code:
CHAR postData[1024];
CHAR postData2[1024];
ZeroMemory(&postData,1024);
ZeroMemory(&postData2,1024);
WinHttpAddRequestHeaders(hRequest,L"Content-Type: multipart/form-data; boundary=----OiRBxC0fjdSEpqhd",-1L,WINHTTP_ADDREQ_FLAG_ADD);
wsprintfA(postData,"%s","----OiRBxC0fjdSEpqhd\r\nContent-Disposition: form-data; name=\"file\"; filename=\"blog.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n");
wsprintfA(postData2,"%s","\r\n----OiRBxC0fjdSEpqhd\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nSubmit\r\n----OiRBxC0fjdSEpqhd--\r\n");
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
lstrlenA(postData)+lstrlenA(postData2)+lSize, NULL);
if (bResults)
{
bResults=WinHttpWriteData(hRequest,LPCVOID)postData,lstrlenA(postData),NULL);
bResults = WinHttpWriteData(hRequest, buffer, lSize, &dwBytesWritten);
bResults=WinHttpWriteData(hRequest,(LPCVOID)postData2,lstrlenA(postData2),NULL);
}
WinHttpWriteData:
POST data - postData, postData2 must be 8 bit encoding.
I tried to can multiply clients, and send it to each one.
But it working only for one, after one client connected the server just useless for incoming connections.
while(true)
{
if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
for(int i = 0; i < MaxUsers; i++)
{
if(!ClientAddress[i].sin_family)
{
ClientAddress[i] = IncomingAddress;
char Version[128], Dir[256], Path[256], URL[128], Message[256];
GetCurrentDirectory(256, Dir);
sprintf(Path, "%s\\Version.ini", Dir);
GetPrivateProfileString("Default", "Version", "1.0.0.0", Version, 128, Path);
GetPrivateProfileString("Default", "URL", "", URL, 128, Path);
GetPrivateProfileString("Default", "Message", "", Message, 256, Path);
send(Sub, Version, 128, 0);
send(Sub, Message, 256, 0);
break;
}
}
continue;
}
}
Of course new clients cannot be accepted because the server handles just accepted client, i.e. the server is busy.
The solution is simple: create a new thread for each accepted client and handle the client session there. Just use _beginthreadex() (#include <process.h>):
unsigned __stdcall ClientSession(void *data)
{
SOCKET client_socket = (SOCKET)data;
// Process the client.
}
int _tmain(int argc, _TCHAR* argv[])
{
...
SOCKET client_socket;
while ((client_socket = accept(server_socket, NULL, NULL))) {
// Create a new thread for the accepted client (also pass the accepted client socket).
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)client_socket, 0, &threadID);
}
}
By the way, send()/recv() functions do not guarantee that all the data would be sent/received at one call. Please see the documentation for return value of these functions.
After accepting socket create separate thread for client requests. Then continue wait for new accepting.
For example:
...
while (1)
{
AcceptSocket = SOCKET_ERROR;
while (AcceptSocket == SOCKET_ERROR )
{
AcceptSocket = accept( m_socket, NULL, NULL );
}
printf( "Client Connected.\n");
DWORD dwThreadId;
CreateThread (NULL, 0, ProcessClient, (LPVOID) AcceptSocket, 0, &dwThreadId);
}
...
Where ProcessClient function could be like this:
DWORD WINAPI ProcessClient (LPVOID lpParameter)
{
SOCKET AcceptSocket = (SOCKET) lpParameter;
// Send and receive data.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[2000]="";
char recvbuf[2000]="";
char timebuf[128];
sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", ipaddr, port);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send hello: %ld\n", WSAGetLastError());
goto fin;
}
while (1)
{
_strtime( timebuf );
ZeroMemory (recvbuf, sizeof(recvbuf));
bytesRecv = recv( AcceptSocket, recvbuf, 32, 0);
printf( "%s Client said: %s\n", timebuf, recvbuf);
if (strcmp(recvbuf, "1") == 0)
{
sprintf(sendbuf, "You typed ONE\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "2") == 0)
{
sprintf(sendbuf, "You typed TWO\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "exit") == 0)
{
printf( "Client has logged out\n", WSAGetLastError());
goto fin;
}
else
{
sprintf(sendbuf, "unknown command\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
}
fin:
printf("Client processed\n");
closesocket(AcceptSocket);
return 0;
}
In the following code the call to SetupDiEnumDeviceInfo() causes the subsequent CreateFile to return ERROR_SHARING_VIOLATION instead of opening the file. I was able to pinpoint the line by commenting out the other pieces of code until I hit one line that would cause the CreateFile to fail.
String SerialATDT::getComPortId()
{
#if 1
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
String comPort = "";
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_MODEM,
0, // Enumerator
0,
DIGCF_PRESENT );
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return "";
}
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
int offset = 0;
while ( SetupDiEnumDeviceInfo(hDevInfo, offset++, &DeviceInfoData) )
{
DWORD DataT;
#if 1
//
// Call function with null to begin with,
// then use the returned buffer size (doubled)
// to Alloc the buffer. Keep calling until
// success or an unknown failure.
//
// Double the returned buffersize to correct
// for underlying legacy CM functions that
// return an incorrect buffersize value on
// DBCS/MBCS systems.
//
while (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_FRIENDLYNAME,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
{
// Change the buffer size.
if (buffer) LocalFree(buffer);
// Double the size to avoid problems on
// W2k MBCS systems per KB 888609.
buffer = (LPTSTR)LocalAlloc(LPTR,buffersize * 2);
}
else
{
// Insert error handling here.
break;
}
}
// Look for identifying info in the name
if ( mComPortIdentifier.size() > 0 ) {
const char *temp = strstr(buffer, mComPortIdentifier.c_str());
if ( temp == 0 ) {
continue;
}
}
// Now find out the port number
DWORD nSize=0 ;
TCHAR buf[MAX_PATH];
if ( SetupDiGetDeviceInstanceId(hDevInfo, &DeviceInfoData, buf, MAX_PATH, &nSize) )
{
HKEY devKey = SetupDiOpenDevRegKey(hDevInfo, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
DWORD size = 0;
DWORD type;
RegQueryValueEx(devKey, TEXT("PortName"), NULL, NULL, NULL, & size);
BYTE* buff = new BYTE[size];
String result;
if( RegQueryValueEx(devKey, TEXT("PortName"), NULL, &type, buff, & size) == ERROR_SUCCESS ) {
comPort = (char*)buff;
if ( comPort.size() > 0 ) {
RegCloseKey(devKey);
break;
}
}
RegCloseKey(devKey);
delete [] buff;
}
#else
comPort = "COM44";
#endif
}
// Cleanup
SetupDiDestroyDeviceInfoList (hDevInfo);
if (buffer) {
LocalFree(buffer);
}
if ( GetLastError()!=NO_ERROR &&
GetLastError()!=ERROR_NO_MORE_ITEMS &&
GetLastError() != ERROR_INVALID_HANDLE )
{
TRACE_L("ATDT error after free %ld", GetLastError() );
// Insert error handling here.
return "";
}
return comPort;
#else
return "COM44";
#endif
}
bool SerialATDT::getComPort(HANDLE *hFile)
{
String comPort = getComPortId();
*hFile = INVALID_HANDLE_VALUE;
if ( comPort.size() > 0 ) {
String comPortStr;
comPortStr.Format("\\\\.\\%s", comPort.c_str());
*hFile = ::CreateFile( comPortStr.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( *hFile == INVALID_HANDLE_VALUE ) {
TRACE_L("AT file open error %ld", GetLastError());
}
}
return *hFile != INVALID_HANDLE_VALUE;
}
I have been looking but have not found a reason why the DeviceInfoData needs to be cleared (nor have I found a method to do it). Has anybody run into this before?