NT4/private/windows/base/advapi/digsig/digsig/java.cpp
2020-09-30 17:12:29 +02:00

954 lines
21 KiB
C++

//
// java.cpp
//
// Java .class file cracker
#include "stdpch.h"
#include "common.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
#define DO(x) { HRESULT hr_ = (x); if (hr == S_OK) hr = hr_; }
int mptagcbConstant[] = {
0, // tag of zero not used
0, // CONSTANT_Utf8
0, // CONSTANT_Unicode
sizeof(CONSTANT_Integer_info),
sizeof(CONSTANT_Float_info),
sizeof(CONSTANT_Long_info),
sizeof(CONSTANT_Double_info),
sizeof(CONSTANT_Class_info),
sizeof(CONSTANT_String_info),
sizeof(CONSTANT_Fieldref_info),
sizeof(CONSTANT_Methodref_info),
sizeof(CONSTANT_InterfaceMethodref_info),
sizeof(CONSTANT_NameAndType_info)
};
int mptagdPoolIndex[] = {
1, // tag of zero not used
1, // CONSTANT_Utf8
1, // CONSTANT_Unicode
1,
1,
2, // CONSTANT_Long
2, // CONSTANT_Double
1,
1,
1,
1,
1,
1
};
static const char szUtf8Signature[] = "_digital_signature_"; // this IS a utf8 string.
static const int cbUtf8Signature = strlen(szUtf8Signature);
/////////////////////////////////////////////////////////////////////////////
//
// Hash functions that hash data in big endian order
//
BOOL Hash(HCRYPTHASH hash, ULONG l)
{
BYTE rgb[4];
rgb[0] = HIBYTE(HIWORD(l));
rgb[1] = LOBYTE(HIWORD(l));
rgb[2] = HIBYTE(LOWORD(l));
rgb[3] = LOBYTE(LOWORD(l));
return CryptHashData(hash, rgb, 4, 0);
}
BOOL Hash(HCRYPTHASH hash, WORD w)
{
BYTE rgb[2];
rgb[0] = HIBYTE(w);
rgb[1] = LOBYTE(w);
return CryptHashData(hash, rgb, 2, 0);
}
BOOL Hash(HCRYPTHASH hash, BYTE b)
{
return CryptHashData(hash, &b, 1, 0);
}
/////////////////////////////////////////////////////////////////////////////
#define H(x) { if (hr==S_OK) { hr = ::Hash(hash, (x)) ? S_OK : HError(); } }
HRESULT CJavaClassFile::Hash(HCRYPTHASH hash)
// Hash the class file. Be careful that this function is invariant irrespective
// of the presence or absence of the signature already being present in the file
{
ULONG i = 0;
HRESULT hr = S_OK;
H(m_magic);
H(m_minor_version);
H(m_major_version);
// We omit the count altogether from the hash, in order as to not be
// sensitive to whether there's a signature or not and to facilitate the
// computation of the hash in a one-pass operation (given that you
// know the hash algorithm to use). This is not a security hole: the
// count bytes are protected by the nature of the message-digest algorithm
// since it is by assumption computationally infeasible to find any two
// distinct messages of any length that have the same message digest.
// This just as in PKCS #7.
/*
if (HasSignature())
H((WORD)(m_constant_pool_count-1));
else
H(m_constant_pool_count);
*/
ULONG iSig = FindSignaturePool();
for (i=i_const_pool_first(); i < i_const_pool_max(); i += mptagdPoolIndex[constant_pool(i).m_tag])
{
if (i != iSig)
DO(constant_pool(i).Hash(hash));
}
H(m_access_flags);
H(m_this_class);
H(m_super_class);
H(m_interfaces_count);
for (i=0; i < m_interfaces_count; i++)
H(m_interfaces[i]);
H(m_fields_count);
for (i=0; i < m_fields_count; i++)
DO(m_fields[i].Hash(hash));
H(m_methods_count);
for (i=0; i < m_methods_count; i++)
DO(m_methods[i].Hash(hash));
//
// Ditto above
/*
if (HasSignature())
H((WORD)(m_attributes_count-1));
else
H(m_attributes_count);
*/
iSig = FindSignatureAttr();
for (i=0; i < m_attributes_count; i++)
{
if (i != iSig)
DO(m_attributes[i].Hash(hash));
}
return hr;
};
HRESULT CJavaConstantPoolInfo::Hash(HCRYPTHASH hash)
{
HRESULT hr = S_OK;
switch (m_tag)
{
case CONSTANT_Utf8: {
H(m_utf8.m_tag);
H(m_utf8.m_length);
if (!CryptHashData(hash, m_utf8.m_bytes, m_utf8.m_length, 0))
hr = HError();
break;
}
case CONSTANT_Unicode: {
H(m_unicode.m_tag);
H(m_unicode.m_length);
if (!CryptHashData(hash, (BYTE*)m_unicode.m_bytes, m_unicode.m_length*2, 0))
hr = HError();
break;
}
case CONSTANT_Integer:
case CONSTANT_Float:
case CONSTANT_Long:
case CONSTANT_Double:
case CONSTANT_Class:
case CONSTANT_String:
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType: {
if (!CryptHashData(hash, &m_fixed.m_rgb[0], m_fixed.m_cb, 0))
hr = HError();
break;
}
default:
NOTREACHED();
hr = E_UNEXPECTED;
};
return hr;
}
HRESULT CJavaAttributeInfo::Hash(HCRYPTHASH hash)
{
HRESULT hr = S_OK;
H(m_attribute_name);
H(m_attribute_length);
if (!CryptHashData(hash, m_info, m_attribute_length, 0))
hr = HError();
return hr;
}
HRESULT CJavaMethodInfo::Hash(HCRYPTHASH hash)
{
HRESULT hr = S_OK;
H(m_access_flags);
H(m_name_index);
H(m_signature_index);
H(m_attributes_count);
for (int i = 0; i<m_attributes_count; i++)
DO(m_attributes[i].Hash(hash));
return hr;
}
HRESULT CJavaFieldInfo::Hash(HCRYPTHASH hash)
{
HRESULT hr = S_OK;
H(m_access_flags);
H(m_name_index);
H(m_signature_index);
H(m_attributes_count);
for (int i = 0; i<m_attributes_count; i++)
DO(m_attributes[i].Hash(hash));
return hr;
}
#undef H
/////////////////////////////////////////////////////////////////////////////
static const GUID IID_IInsertSig = { 0xb0e89ba2, 0x68b6, 0x11cf, { 0xb1, 0xe5, 0x0, 0xaa, 0x0, 0x6c, 0x37, 0x6 } };
HRESULT CJavaClassFile::LoadSig(BLOB* pblob)
// Extract and return the signature, if present. If not, return STG_E_FILENOTFOUND.
{
HRESULT hr = S_OK;
Zero(*pblob);
int i = FindSignatureAttr();
if (i == -1)
{
hr = STG_E_FILENOTFOUND;
}
else
{
if (!CopyToTaskMem(pblob, m_attributes[i].m_attribute_length, m_attributes[i].m_info))
hr = E_OUTOFMEMORY;
}
return hr;
}
HRESULT CJavaClassFile::SaveSig(BLOB* pblob)
// Save the signature block into an attribute in the class file
{
HRESULT hr = S_OK;
int i = FindSignatureAttr();
if (i == -1)
{
// Not there. Make a new attribute which is the signature.
//
// First, make the new constant pool entry, growing the constant pool
CJavaConstantPoolInfo* pNewPool = new CJavaConstantPoolInfo[m_constant_pool_count+1];
if (pNewPool)
{
// copy the pool over
for (ULONG j = 0; j<m_constant_pool_count; j++)
{
pNewPool[j] = m_constant_pool[j];
m_constant_pool[j].Init();
}
delete [] m_constant_pool;
m_constant_pool = pNewPool;
m_constant_pool_count += 1;
}
else
hr = E_OUTOFMEMORY;
// Set the last pool entry to be the signature name
if (hr == S_OK)
{
CJavaConstantPoolInfo& cp = constant_pool(i_const_pool_last());
cp.m_tag = CONSTANT_Utf8;
cp.m_utf8.m_tag = CONSTANT_Utf8;
cp.m_utf8.m_bytes = new BYTE[cbUtf8Signature];
if (cp.m_utf8.m_bytes)
{
cp.m_utf8.m_length = cbUtf8Signature;
memcpy(cp.m_utf8.m_bytes, szUtf8Signature, cbUtf8Signature);
}
else
hr = E_OUTOFMEMORY;
}
// Next, make the new attribute itself
//
if (hr == S_OK)
{
CJavaAttributeInfo* pNewAttributes = new CJavaAttributeInfo[m_attributes_count+1];
if (pNewAttributes)
{
for (int j=0; j<m_attributes_count; j++)
{
pNewAttributes[j] = m_attributes[j];
m_attributes[j].Init();
}
delete [] m_attributes;
m_attributes = pNewAttributes;
m_attributes_count += 1;
}
else
hr = E_OUTOFMEMORY;
// Set the last attribute to be the signature block
if (hr == S_OK)
{
i = m_attributes_count-1;
m_attributes[i].m_attribute_name = (WORD)i_const_pool_last();
ASSERT(IsSignatureAttr(i));
ASSERT(IsSignaturePool(m_attributes[i].m_attribute_name));
goto SetSig;
}
}
}
else
{
// Already there. Replace the existing signature attribute
delete [] m_attributes[i].m_info;
SetSig:
m_attributes[i].m_attribute_length = 0;
m_attributes[i].m_info = new BYTE[pblob->cbSize];
if (m_attributes[i].m_info)
{
m_attributes[i].m_attribute_length = pblob->cbSize;
memcpy(m_attributes[i].m_info, pblob->pBlobData, pblob->cbSize);
}
else
hr = E_OUTOFMEMORY;
}
#ifdef _DEBUG
if (hr == S_OK)
{
BLOB b;
GOOD(LoadSig(&b));
ASSERT(IsEqual(b, *pblob));
FreeTaskMem(b);
};
#endif
MakeDirty();
return hr;
}
/////////////////////////////////////////////////////////////////////////////
BOOL CJavaClassFile::IsSignatureAttr(int i)
// Answer as to whether the given attribute index is the signature.
//
// The signature attribute:
//
// 1) has name "_digital_signature"
// 2) is the LAST attribute with such a name
// 3) must use as its name the LAST constant pool entry of type CONSTANT_Utf8
// and value "_digital_signature"
// 4) must be the only reference to that constant
//
// We _locate_ the signature using only the first two of these points;
// it is when we _add_ the signature that we ensure (by construction) the
// latter two points.
//
// Further, we ASSUME that _all_ conforming implementations will also maintain
// points 3) and 4), so we don't explicitly check for it.
{
if (IsDigSig(m_attributes[i].m_attribute_name))
{
for (int j = i+1; j<m_attributes_count; j++)
{
if (IsDigSig(m_attributes[j].m_attribute_name))
return FALSE;
}
return TRUE;
}
else
return FALSE;
}
BOOL CJavaClassFile::IsDigSig(int i)
// Answer as to whether the indicated constant pool entry has a name which
// could be the name of the signature attribute
{
CJavaConstantPoolInfo& cp = constant_pool(i);
if (cp.m_tag == CONSTANT_Utf8
&& cp.m_utf8.m_length == cbUtf8Signature
&& memcmp(cp.m_utf8.m_bytes, szUtf8Signature, cbUtf8Signature) == 0)
{
return TRUE;
}
return FALSE;
}
BOOL CJavaClassFile::IsSignaturePool(int i)
// Answer as to whether the pool index is the constant which is the name of
// the signature.
{
return FindSignaturePool() == i;
}
int CJavaClassFile::FindSignaturePool()
// Return the index, if any, of the constant pool entry which is the name
// of the signature
{
int i = FindSignatureAttr();
if (i == -1)
return -1;
else
return m_attributes[i].m_attribute_name;
}
int CJavaClassFile::FindSignatureAttr()
// Return the index of the attribute which has the signature, or -1 if no
// such attribute exists
{
int i;
for (i = 0; i < m_attributes_count; i++)
{
if (IsSignatureAttr(i))
return i;
}
return -1;
}
BOOL CJavaClassFile::HasSignature()
// Answer as to whether we presently have a signature in this class file
// or not.
{
return FindSignatureAttr() != -1;
}
HRESULT CJavaClassFile::Load(IStream*pstm)
{
ULONG i;
Free();
HRESULT hr = S_OK;
DO(u4(pstm, & m_magic));
if (hr == S_OK && m_magic == 0xCAFEBABE)
{
DO(u2(pstm, & m_minor_version));
DO(u2(pstm, & m_major_version));
DO(u2(pstm, & m_constant_pool_count));
if (hr == S_OK)
{
m_constant_pool = new CJavaConstantPoolInfo[m_constant_pool_count];
if (m_constant_pool)
{
for (i=i_const_pool_first(); i<i_const_pool_max(); i += mptagdPoolIndex[constant_pool(i).m_tag])
DO(constant_pool(i).Load(pstm));
}
else
{
m_constant_pool_count = 0;
hr = E_OUTOFMEMORY;
}
}
DO(u2(pstm, & m_access_flags));
DO(u2(pstm, & m_this_class));
DO(u2(pstm, & m_super_class));
DO(u2(pstm, & m_interfaces_count));
if (hr == S_OK)
{
m_interfaces = new WORD[m_interfaces_count];
if (m_interfaces)
{
for (i=0; i<m_interfaces_count; i++)
DO(u2(pstm, &m_interfaces[i]));
}
else
{
m_interfaces_count = 0;
hr = E_OUTOFMEMORY;
}
}
DO(u2(pstm, & m_fields_count));
if (hr == S_OK)
{
m_fields = new CJavaFieldInfo[m_fields_count];
if (m_fields)
{
for (i=0; i<m_fields_count; i++)
DO(m_fields[i].Load(pstm));
}
else
{
m_fields_count = 0;
hr = E_OUTOFMEMORY;
}
}
DO(u2(pstm, & m_methods_count));
if (hr == S_OK)
{
m_methods = new CJavaMethodInfo[m_methods_count];
if (m_methods)
{
for (i=0; i<m_methods_count; i++)
DO(m_methods[i].Load(pstm));
}
else
{
m_methods_count = 0;
hr = E_OUTOFMEMORY;
}
}
DO(u2(pstm, & m_attributes_count));
if (hr == S_OK)
{
m_attributes = new CJavaAttributeInfo[m_attributes_count];
if (m_attributes)
{
for (i=0; i<m_attributes_count; i++)
DO(m_attributes[i].Load(pstm));
}
else
{
m_attributes_count = 0;
hr = E_OUTOFMEMORY;
}
}
}
else
hr = E_UNEXPECTED;
m_isDirty = FALSE;
return hr;
}
HRESULT CJavaClassFile::Save(IStream*pstm, BOOL fClearDirty)
{
ULONG i;
HRESULT hr = S_OK;
DO(u4(pstm, m_magic));
DO(u2(pstm, m_minor_version));
DO(u2(pstm, m_major_version));
DO(u2(pstm, m_constant_pool_count));
for (i=i_const_pool_first(); i<i_const_pool_max(); i += mptagdPoolIndex[constant_pool(i).m_tag])
DO(constant_pool(i).Save(pstm));
DO(u2(pstm, m_access_flags));
DO(u2(pstm, m_this_class));
DO(u2(pstm, m_super_class));
DO(u2(pstm, m_interfaces_count));
for (i=0; i<m_interfaces_count; i++)
DO(u2(pstm, m_interfaces[i]));
DO(u2(pstm, m_fields_count));
for (i=0; i<m_fields_count; i++)
DO(m_fields[i].Save(pstm));
DO(u2(pstm, m_methods_count));
for (i=0; i<m_methods_count; i++)
DO(m_methods[i].Save(pstm));
DO(u2(pstm, m_attributes_count));
for (i=0; i<m_attributes_count; i++)
DO(m_attributes[i].Save(pstm));
if (hr == S_OK)
{
if (fClearDirty)
m_isDirty = FALSE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
CJavaConstantPoolInfo::CJavaConstantPoolInfo()
{
Init();
}
CJavaConstantPoolInfo::~CJavaConstantPoolInfo()
{
Free();
}
void CJavaConstantPoolInfo::Init()
{
m_tag = 0;
Zero(m_unicode);
Zero(m_fixed);
Zero(m_utf8);
}
void CJavaConstantPoolInfo::Free()
{
switch (m_tag)
{
case CONSTANT_Utf8:
if (m_utf8.m_bytes)
delete [] m_utf8.m_bytes;
break;
case CONSTANT_Unicode:
if (m_unicode.m_bytes)
delete [] m_utf8.m_bytes;
break;
default:
/* do nothing */;
}
Init();
}
HRESULT CJavaConstantPoolInfo::Load(IStream*pstm)
{
Free();
HRESULT hr = S_OK;
hr = Peek(pstm, &m_tag, 1);
if (hr == S_OK)
{
switch (m_tag)
{
case CONSTANT_Utf8: {
u1(pstm, &m_utf8.m_tag);
u2(pstm, &m_utf8.m_length);
m_utf8.m_bytes = new BYTE[m_utf8.m_length];
if (m_utf8.m_bytes)
hr = Read(pstm, m_utf8.m_bytes, m_utf8.m_length); // No null termination
else
hr = E_OUTOFMEMORY;
break;
}
case CONSTANT_Unicode: {
u1(pstm, &m_unicode.m_tag);
u2(pstm, &m_unicode.m_length);
m_unicode.m_bytes = new WORD[m_unicode.m_length];
if (m_unicode.m_bytes)
hr = Read(pstm, m_unicode.m_bytes, m_unicode.m_length*sizeof(WORD)); // no null termination
else
hr = E_OUTOFMEMORY;
break;
}
case CONSTANT_Integer:
case CONSTANT_Float:
case CONSTANT_Long:
case CONSTANT_Double:
case CONSTANT_Class:
case CONSTANT_String:
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType: {
m_fixed.m_cb = mptagcbConstant[m_tag];
ASSERT(m_fixed.m_cb <= sizeof(m_fixed.m_rgb));
hr = Read(pstm, &m_fixed.m_rgb[0], m_fixed.m_cb);
break;
}
default:
NOTREACHED();
hr = E_UNEXPECTED;
};
}
return hr;
}
HRESULT CJavaConstantPoolInfo::Save(IStream*pstm)
{
HRESULT hr = S_OK;
switch (m_tag)
{
case CONSTANT_Utf8: {
DO(u1(pstm, m_utf8.m_tag));
DO(u2(pstm, m_utf8.m_length));
DO(Write(pstm, m_utf8.m_bytes, m_utf8.m_length));
break;
}
case CONSTANT_Unicode: {
DO(u1(pstm, m_unicode.m_tag));
DO(u2(pstm, m_unicode.m_length));
DO(Write(pstm, m_unicode.m_bytes, m_unicode.m_length));
break;
}
case CONSTANT_Integer:
case CONSTANT_Float:
case CONSTANT_Long:
case CONSTANT_Double:
case CONSTANT_Class:
case CONSTANT_String:
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType: {
hr = Write(pstm, &m_fixed.m_rgb[0], m_fixed.m_cb);
break;
}
default:
NOTREACHED();
hr = E_UNEXPECTED;
};
return hr;
}
/////////////////////////////////////////////////////////////////////////////
CJavaAttributeInfo::CJavaAttributeInfo()
{
Init();
}
CJavaAttributeInfo::~CJavaAttributeInfo()
{
Free();
}
void CJavaAttributeInfo::Init()
{
m_attribute_name = 0;
m_attribute_length = 0;
m_info = 0;
}
void CJavaAttributeInfo::Free()
{
if (m_info)
delete [] m_info;
Init();
}
HRESULT CJavaAttributeInfo::Load(IStream*pstm)
{
Free();
HRESULT hr = S_OK;
DO(u2(pstm,&m_attribute_name));
DO(u4(pstm,&m_attribute_length));
if (hr == S_OK)
{
m_info = new BYTE[m_attribute_length];
if (m_info)
hr = Read(pstm, m_info, m_attribute_length);
else
{
m_attribute_length = 0;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
HRESULT CJavaAttributeInfo::Save(IStream*pstm)
{
HRESULT hr = S_OK;
DO(u2(pstm,m_attribute_name));
DO(u4(pstm,m_attribute_length));
if (hr == S_OK && m_info)
{
hr = Write(pstm, m_info, m_attribute_length);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
CJavaMethodInfo::CJavaMethodInfo()
{
Init();
}
CJavaMethodInfo::~CJavaMethodInfo()
{
Free();
}
void CJavaMethodInfo::Init()
{
m_access_flags = 0;
m_name_index = 0;
m_signature_index = 0;
m_attributes_count = 0;
m_attributes = NULL;
}
void CJavaMethodInfo::Free()
{
if (m_attributes)
delete [] m_attributes;
Init();
}
HRESULT CJavaMethodInfo::Load(IStream* pstm)
{
Free();
HRESULT hr = S_OK;
DO(u2(pstm, & m_access_flags));
DO(u2(pstm, & m_name_index));
DO(u2(pstm, & m_signature_index));
DO(u2(pstm, & m_attributes_count));
if (hr == S_OK)
{
m_attributes = new CJavaAttributeInfo[m_attributes_count];
if (m_attributes)
{
for (int i=0; i<m_attributes_count; i++)
DO(m_attributes[i].Load(pstm));
}
else
{
hr = E_OUTOFMEMORY;
m_attributes_count = 0;
}
}
return hr;
}
HRESULT CJavaMethodInfo::Save(IStream* pstm)
{
HRESULT hr = S_OK;
DO(u2(pstm, m_access_flags));
DO(u2(pstm, m_name_index));
DO(u2(pstm, m_signature_index));
DO(u2(pstm, m_attributes_count));
if (hr == S_OK && m_attributes)
{
for (int i=0; i<m_attributes_count; i++)
DO(m_attributes[i].Save(pstm));
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
CJavaFieldInfo::CJavaFieldInfo()
{
Init();
}
CJavaFieldInfo::~CJavaFieldInfo()
{
Free();
}
void CJavaFieldInfo::Init()
{
m_access_flags = 0;
m_name_index = 0;
m_signature_index = 0;
m_attributes_count = 0;
m_attributes = NULL;
}
void CJavaFieldInfo::Free()
{
if (m_attributes)
delete [] m_attributes;
Init();
}
HRESULT CJavaFieldInfo::Load(IStream* pstm)
{
Free();
HRESULT hr = S_OK;
DO(u2(pstm, &m_access_flags));
DO(u2(pstm, &m_name_index));
DO(u2(pstm, &m_signature_index));
DO(u2(pstm, &m_attributes_count));
if (hr == S_OK)
{
m_attributes = new CJavaAttributeInfo[m_attributes_count];
if (m_attributes)
{
for (int i=0; i<m_attributes_count; i++)
{
DO(m_attributes[i].Load(pstm));
}
}
else
{
hr = E_OUTOFMEMORY;
m_attributes_count = 0;
}
}
return hr;
}
HRESULT CJavaFieldInfo::Save(IStream* pstm)
{
HRESULT hr = S_OK;
DO(u2(pstm, m_access_flags));
DO(u2(pstm, m_name_index));
DO(u2(pstm, m_signature_index));
DO(u2(pstm, m_attributes_count));
if (hr == S_OK && m_attributes)
{
for (int i=0; i<m_attributes_count; i++)
{
DO(m_attributes[i].Save(pstm));
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
HRESULT CJavaReaderWriter::Read(IStream* pstm, LPVOID pBuff, ULONG cb)
{
ULONG cbRead;
pstm->Read(pBuff, cb, &cbRead);
return cb == cbRead ? S_OK : STG_E_MEDIUMFULL;
}
HRESULT CJavaReaderWriter::Peek(IStream* pstm, LPVOID pBuff, ULONG cb)
{
ULARGE_INTEGER ulCur;
HRESULT hr = pstm->Seek(llZero, STREAM_SEEK_CUR, &ulCur);
if (hr == S_OK)
{
hr = Read(pstm, pBuff, cb);
if (hr == S_OK)
{
LARGE_INTEGER ll;
ll.QuadPart = ulCur.QuadPart;
hr = pstm->Seek(ll, STREAM_SEEK_SET, NULL);
}
}
return hr;
}
HRESULT CJavaReaderWriter::Write(IStream* pstm, LPVOID pBuff, ULONG cb)
{
ULONG cbWritten;
pstm->Write(pBuff, cb, &cbWritten);
return cb == cbWritten ? S_OK : STG_E_MEDIUMFULL;
}
HRESULT CJavaReaderWriter::u4(IStream*pstm, ULONG*pul)
{
BYTE rgb[4];
HRESULT hr = Read(pstm, rgb, 4);
if (hr == S_OK)
{
*pul = ((ULONG)rgb[0]<<24)
+ ((ULONG)rgb[1]<<16)
+ ((ULONG)rgb[2]<<8)
+ ((ULONG)rgb[3]<<0);
}
return hr;
}
HRESULT CJavaReaderWriter::u4(IStream*pstm, ULONG ul)
{
BYTE rgb[4];
rgb[0] = HIBYTE(HIWORD(ul));
rgb[1] = LOBYTE(HIWORD(ul));
rgb[2] = HIBYTE(LOWORD(ul));
rgb[3] = LOBYTE(LOWORD(ul));
return Write(pstm, rgb, 4);
}
HRESULT CJavaReaderWriter::u2(IStream*pstm, WORD*pw)
{
BYTE rgb[2];
HRESULT hr = Read(pstm, rgb, 2);
if (hr == S_OK)
{
*pw = ((WORD)rgb[0]<<8)
+ ((WORD)rgb[1]<<0);
}
return hr;
}
HRESULT CJavaReaderWriter::u2(IStream*pstm, WORD w)
{
BYTE rgb[2];
rgb[0] = HIBYTE(w);
rgb[1] = LOBYTE(w);
return Write(pstm, rgb, 2);
}
HRESULT CJavaReaderWriter::u1(IStream*pstm, BYTE* pb)
{
return Read(pstm, pb, 1);
}
HRESULT CJavaReaderWriter::u1(IStream*pstm, BYTE b)
{
return Write(pstm, &b, 1);
}