|
Hi,
Can I attach binary data to the http stream ?
As I know, for our sending binary data, we need to encode it by base64,
but it will lead to larger data size for transfer, so can I directly
attach binary data to the http stream ? Does the http specification
allow it ? And will it be blocked by firewall ?
Thanks
|
|
|
|
|
The http headers of the response specify the content-type and encoding of the body, which according to them, can be binary. In fact, that's how files are usually downloaded (e.g., .exe, .zip, .jpg).
For example, the following are the headers of the http response after submitting a GET for http://www.codeproject.com/images/standard/logo225x72.gif:
Server: Microsoft-IIS/5.0
X-Powered-By: ASP.NET
Cache-Control: max-age=86400
Expires: Wed, 21 Sep 2005 03:57:21 GMT
Connection: close
Date: Tue, 20 Sep 2005 03:57:21 GMT
Content-Type: image/gif
Accept-Ranges: bytes
Last-Modified: Fri, 16 Nov 2001 00:10:57 GMT
ETag: "f076372a336ec11:8b1"
Content-Length: 5826
After those headers comes the response, which in this case is binary data (i.e., 5826 bytes)
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
So this is the first time I'm doing anything more complex with CryptoAPI than a MD5 hash, and in typical MS fashion the API is over-complex and under-documented. Anyhoo, I'm trying to generate a public/private key pair so I can ship the public key in an app and write an encrypted log file (the thinking being that only my log viewer will have the private key so no one else could read sensitive data in the log). Problem is, I'm able to encrypt and decrypt using just the public key. WTF?
Here's how I created the keys. Error handling has been omitted here but all calls are succeeding in my test app.
HCRYPTPROV hcp;
HCRYPTKEY hcc;
if ( !CryptAcquireContext ( &hcp, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0 ) &&
GetLastError() == NTE_BAD_KEYSET )
{
CryptAcquireContext ( &hcp, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET ) )
}
<font color=red>
CryptGenKey ( hcp, CALG_RSA_KEYX, (4096<<16)|CRYPT_EXPORTABLE, &hcc );
DWORD cbyBlob = 0;
BYTE* pbyPublicBlob = NULL, *pbyPrivateBlob = NULL;
CryptExportKey ( hcc, NULL, PUBLICKEYBLOB, 0, NULL, &cbyBlob );
pbyPublicBlob = new BYTE[cbyBlob];
CryptExportKey ( hcc, NULL, PUBLICKEYBLOB, 0, pbyPublicBlob, &cbyBlob );
CryptExportKey ( hcc, NULL, PRIVATEKEYBLOB, 0, NULL, &cbyBlob );
pbyPrivateBlob = new BYTE[cbyBlob];
CryptExportKey ( hcc, NULL, PRIVATEKEYBLOB, 0, pbyPrivateBlob, &cbyBlob );
That's all fine and dandy and I end up with two byte arrays:
BYTE abyPublicKey[] = { ... };
BYTE abyPrivateKey[] = { ... }; So now when I test importing just the public key, I can do this:
HCRYPTKEY hpubkey;
CryptImportKey ( hcp, abyPublicKey, sizeof(abyPublicKey), NULL, 0, &hpubkey );
BYTE thetext[] = "The Code Project", *pbyBuffer = NULL;
DWORD cbyPlainText = sizeof(thetext), cbyCipherText = 0;
CryptEncrypt ( hpubkey, NULL, TRUE, 0, NULL, &cbyCipherText, cbyPlainText );
pbyBuffer = new BYTE[cbyCipherText];
memcpy ( pbyBuffer, thetext, cbyPlainText );
CryptEncrypt ( hpubkey, NULL, TRUE, 0, pbyBuffer, &cbyPlainText, cbyCipherText );
BYTE* pbyDecrypted = new BYTE[cbyCipherText];
memcpy ( pbyDecrypted, pbyBuffer, cbyCipherText );
<font color=red></font>
CryptDecrypt ( hpubkey, NULL, TRUE, 0, pbyDecrypted, &cbyCipherText ); The same public key results in successful calls to CryptEncrypt() and CryptDecrypt() . So either I'm doing something dumb (which is possible, I'm not used to this API yet) or I didn't really get a pub/private key pair from CryptGenKey() . Any ideas?
--Mike--
Visual C++ MVP
LINKS~! Ericahist | 1ClickPicGrabber | NEW~! CP SearchBar v3.0 | C++ Forum FAQ
Pinky, are you pondering what I'm pondering?
I think so Brain, but how will we fit the hamster inside the accordion?
-- modified at 22:22 Monday 19th September, 2005
|
|
|
|
|
Is your result right? Is the DecryptedText be equal to plainText?
|
|
|
|
|
Yeah, that's why I'm asking the question in the first place. The same key shouldn't be able to encrypt and decrypt the same data, no?
--Mike--
Visual C++ MVP
LINKS~! Ericahist | 1ClickPicGrabber | NEW~! CP SearchBar v3.0 | C++ Forum FAQ
Strange things are afoot at the U+004B U+20DD
|
|
|
|
|
(Posting the answer in case anyone ever sees this)
After much trial and much more error, I groked how the API works. When you call CryptExportKey(PRIVATEKEYBLOB) you actually get both keys in the blob. Also, while I was importing the public key in my code, both keys were already in my key store since I generated them on the same box, so CryptDecript() was automagically using the other key in the pair.
So calling CryptAcquireContext() with CRYPT_DELETEKEYSET removed the keys from the store; then if I import just the public key it can't encrypt then decrypt the same data. whee.
--Mike--
Visual C++ MVP
LINKS~! Ericahist | 1ClickPicGrabber | NEW~! CP SearchBar v3.0 | C++ Forum FAQ
"Linux is good. It can do no wrong. It is open source so must be right. It has penguins. I want to eat your brain."
-- Paul Watson, Linux Zombie
|
|
|
|
|
Is there a line of code that can convert an integer into a CString type?
When displaying texts, messages or reports, edit boxes has a member variable of type CString. I'd like to add a variable of integer type into the its original member variable which is CString-type. Thanks
|
|
|
|
|
It sounds like you're using MFC's DDX? If so, just make another variable that's an int - you aren't limited to one variable per control
--Mike--
Visual C++ MVP
LINKS~! Ericahist | 1ClickPicGrabber | NEW~! CP SearchBar v3.0 | C++ Forum FAQ
There is a saying in statistics that a million monkeys pounding on typewriters would eventually create a work of Shakespeare. Thanks to the Internet, we now know that this is not true.
|
|
|
|
|
If I get you right, you wan't to put an int value as a readable value in a CString, right?
In that case, you could use the CString member Format(). An example:
CString cs;
int i = 47;
cs.Format("Decimal value of i: %d, hexadecimal value of i: %04X.", i, i);
|
|
|
|
|
Hi!
When I use DeviceIoControl() to communicate with a special
device in my VC++ application,the DeviceIoControl() returns
zero,and the Getlasterror() returns 50.
I defined an IOCTL command in my driver,and used CreateFile to retrieve the device handle.
I set a breakpoint at IRP dispatch instance in my driver code with SoftICE,
but it seems that the DeviceIoControl() can not communictate with the driver.
What's the matter then?
Thanks for help!
momer
-- modified at 2:03 Tuesday 20th September, 2005
|
|
|
|
|
code:
AfxBeginThread(DoTimer, 0);
error: none of the 2 overloads can convert parameter 1 from type 'unsigned int (void *)'
DoTimer declaration:
UINT DoTimer(LPVOID pParam)
{
....
}
what's wrong? I've seen it from an example.
|
|
|
|
|
change AfxBeginThread(DoTimer, 0); to AfxBeginThread(DoTimer, NULL);
|
|
|
|
|
Josh Gray wrote:
change AfxBeginThread(DoTimer, 0); to AfxBeginThread(DoTimer, NULL);
didn't worked
|
|
|
|
|
sorry my nmistake. Try AfxBeginThread( (AFX_THREADPROC)DoTimer, NULL);
|
|
|
|
|
benjnp wrote:
AfxBeginThread(DoTimer, 0);
works fine as long as I don't call the functions that are built on the same class. Meaning, it can't call other functions or use the variables of that class.
I want to create a thread for a specific function only, of course having the UINT type and (LPVOID param) parameter that may call/use other members of the class. How?
|
|
|
|
|
benjnp wrote:
works fine as long as I don't call the functions that are built on the same class
That's your problem ! You cannot use member functions of a class for that ? Why ? Simply because they have another calling convention than the "standard" functions: the this parameter is passed implicitely as parameter of the function.
A way to have it working: use a global function as callback (instead of DoTimer) and pass the pointer of the current class as parameter (instead of the 0). So like that in your function you will be able to do something like:
UINT MyGlobalFunc(LPVOID pParam)<br />
{<br />
CMyClass* pObject = (CMyClass*)pParam;<br />
pObject->DoTimer();
}
And to start your thread:
AfxBeginThread(MyGlobalFunc,this);
Hope this helps
|
|
|
|
|
Hi,
Try casting the DoTimer to AFX_THREADPROC.
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
RichardS wrote:
Try casting the DoTimer to AFX_THREADPROC.
How? a very simple snippet will do. Thanx
|
|
|
|
|
AfxBeginThread ((AFX_THREADPROC)DoTimer, 0);
BTW, the reason for the cast is that there are calling symantics between C and C++. The function to create threads needs C calling scheme but the function is a C++ function (even though it is not part of class). By casting it you are not "breaking" anything you are mearly telling the compiler to treat the function as a C function, which it can be.
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proof programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
First off, do NOT take the advice of people who say "Just cast it to "AFX_THREADPROC". The compiler is whining because something is wrong. Casting it just hides that without really fixing the advice. Very very very bad advice.
Have you defined DoTimer inside of a class? If so, then don't. It should be a global function or a static member function in a class.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
benjnp wrote:
error: none of the 2 overloads can convert parameter 1 from type 'unsigned int (void *)'
Cannot convert from type 'unsigned int (void *)' to what? That part of the error message is the key...
AfxBeginThread expects the function you pass to be defined as follows:
UINT __cdecl DoTimer(LPVOID pParam)
{
....
}
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
that's the whole error msg, I'm also looking for it when i first saw it
|
|
|
|
|
If the thread function is a member function it has to be declared 'static'.
Usually when I use worker threads I have one function for starting the thread and one for stopping it, all declared in the class.
Before your app exits you want to be sure that you have no worker threads still running.
Below is a skeleton to build your thread functionality on. You can read more about it in MSDN.
class CTest
{
CTest() { m_pThread = NULL; }
~CTest() { StopThread(); }
.....
protected:
CWinThread* m_pThread;
volatile BOOL m_fStopThread;
BOOL StartThread()
{
StopThread();
m_fStopThread = FALSE;
m_pThread = AfxBeginThread( ThreadFn, this, 0, 0, CREATE_SUSPENDED, NULL );
if( m_pThread )
{
m_pThread->m_bAutoDelete = FALSE;
m_pThread->ResumeThread();
}
return (m_pThread != NULL);
}
void StopThread()
{
m_fStopThread = TRUE;
if( m_pThread )
{
::WaitForSingleObject( m_pThread->m_hThread, INFINITE );
delete m_pThread;
m_pThread = NULL;
}
}
static UINT ThreadFn( LPVOID pThis )
{
return ((Ctest*)pThis)->ThreadFn();
}
UINT ThreadFn()
{
while( !m_fStopThread );
return 0;
}
};
Hope this helps
--
Roger
|
|
|
|
|
You don't have to cast anything!!
<br />
class CMyThread<br />
{<br />
public:<br />
<br />
CMyThread() {};<br />
~CMyThread() {};<br />
<br />
static UINT MyStaticClassBeginThreadProc( LPVOID pParam);<br />
<br />
protected:<br />
int m_iSomeMember;<br />
int m_iThreadState;<br />
};<br />
<br />
UINT CMyThread::MyStaticClassBeginThreadProc( LPVOID pParam)<br />
{<br />
CMyThread *pSelf = (CMyThread *)pParam;<br />
<br />
pSelf->m_iSomeMember = 1;<br />
pSelf->m_iThreadState = 0;<br />
<br />
return 0;<br />
};<br />
<br />
<br />
UINT MyGlobalBeginThreadProc( LPVOID pParam)<br />
{<br />
return 0;<br />
};<br />
<br />
typedef struct<br />
{<br />
int iLen;<br />
int iState;<br />
char cType;<br />
} SOMETHREADDATA;<br />
<br />
<br />
<br />
SOMETHREADDATA threadData;<br />
CWinThread *pThread;<br />
CMyThread thread;
pThread = AfxBeginThread( MyGlobalBeginThreadProc, (LPVOID*)&threadData);<br />
pThread = AfxBeginThread( CMyThread::MyStaticClassBeginThreadProc, (LPVOID*)&thread);<br />
:->
|
|
|
|
|
I tried your idea and it work a bit when accessing a member function of the same class, BUT that member function must be stand-alone. I mean. if I put or access some member variables of the same class, a run-time error occured (MFC4d.dll has an error).
|
|
|
|
|