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.
670 lines
17 KiB
670 lines
17 KiB
// convert.cpp : implementation file
|
|
//
|
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
#include "wordpad.h"
|
|
#include "multconv.h"
|
|
#include "mswd6_32.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#ifdef CONVERTERS
|
|
CConverter* CConverter::m_pThis = NULL;
|
|
#endif
|
|
|
|
#define BUFFSIZE 4096
|
|
|
|
CTrackFile::CTrackFile(CFrameWnd* pWnd) : CFile()
|
|
{
|
|
m_nLastPercent = -1;
|
|
m_dwLength = 0;
|
|
m_pFrameWnd = pWnd;
|
|
VERIFY(m_strComplete.LoadString(IDS_COMPLETE));
|
|
VERIFY(m_strWait.LoadString(IDS_PLEASE_WAIT));
|
|
VERIFY(m_strSaving.LoadString(IDS_SAVING));
|
|
// OutputPercent(0);
|
|
}
|
|
|
|
CTrackFile::~CTrackFile()
|
|
{
|
|
OutputPercent(100);
|
|
if (m_pFrameWnd != NULL)
|
|
m_pFrameWnd->SetMessageText(AFX_IDS_IDLEMESSAGE);
|
|
}
|
|
|
|
UINT CTrackFile::Read(void FAR* lpBuf, UINT nCount)
|
|
{
|
|
UINT n = CFile::Read(lpBuf, nCount);
|
|
if (m_dwLength != 0)
|
|
OutputPercent((int)((GetPosition()*100)/m_dwLength));
|
|
return n;
|
|
}
|
|
|
|
void CTrackFile::Write(const void FAR* lpBuf, UINT nCount)
|
|
{
|
|
CFile::Write(lpBuf, nCount);
|
|
OutputString(m_strSaving);
|
|
// if (m_dwLength != 0)
|
|
// OutputPercent((int)((GetPosition()*100)/m_dwLength));
|
|
}
|
|
|
|
void CTrackFile::OutputString(LPCTSTR lpsz)
|
|
{
|
|
if (m_pFrameWnd != NULL)
|
|
{
|
|
m_pFrameWnd->SetMessageText(lpsz);
|
|
CWnd* pBarWnd = m_pFrameWnd->GetMessageBar();
|
|
if (pBarWnd != NULL)
|
|
pBarWnd->UpdateWindow();
|
|
}
|
|
}
|
|
|
|
void CTrackFile::OutputPercent(int nPercentComplete)
|
|
{
|
|
if (m_pFrameWnd != NULL && m_nLastPercent != nPercentComplete)
|
|
{
|
|
m_nLastPercent = nPercentComplete;
|
|
TCHAR buf[64];
|
|
int n = nPercentComplete;
|
|
if (SUCCEEDED(StringCchPrintf(buf, ARRAYSIZE(buf), (n==100) ? m_strWait : m_strComplete, n)))
|
|
{
|
|
OutputString(buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
COEMFile::COEMFile(CFrameWnd* pWnd) : CTrackFile(pWnd)
|
|
{
|
|
}
|
|
|
|
UINT COEMFile::Read(void FAR* lpBuf, UINT nCount)
|
|
{
|
|
UINT n = CTrackFile::Read(lpBuf, nCount);
|
|
OemToCharBuffA((const char*)lpBuf, (char*)lpBuf, n);
|
|
return n;
|
|
}
|
|
|
|
void COEMFile::Write(const void FAR* lpBuf, UINT nCount)
|
|
{
|
|
CharToOemBuffA((const char*)lpBuf, (char*)lpBuf, nCount);
|
|
CTrackFile::Write(lpBuf, nCount);
|
|
}
|
|
|
|
#ifdef CONVERTERS
|
|
|
|
HGLOBAL CConverter::StringToHGLOBAL(LPCSTR pstr)
|
|
{
|
|
HGLOBAL hMem = NULL;
|
|
if (pstr != NULL)
|
|
{
|
|
size_t cch = (lstrlenA(pstr)*2) + 1; // Why are we allocating this much?
|
|
hMem = GlobalAlloc(GHND, cch);
|
|
if (NULL == hMem)
|
|
AfxThrowMemoryException();
|
|
char* p = (char*) GlobalLock(hMem);
|
|
if (p != NULL)
|
|
EVAL(StringCchCopyA(p, cch, pstr) == S_OK);
|
|
GlobalUnlock(hMem);
|
|
}
|
|
return hMem;
|
|
}
|
|
|
|
CConverter::CConverter(LPCTSTR pszLibName, CFrameWnd* pWnd) : CTrackFile(pWnd)
|
|
{
|
|
USES_CONVERSION;
|
|
m_hBuff = NULL;
|
|
m_pBuf = NULL;
|
|
m_nBytesAvail = 0;
|
|
m_nBytesWritten = 0;
|
|
m_nPercent = 0;
|
|
m_hEventFile = NULL;
|
|
m_hEventConv = NULL;
|
|
m_bDone = TRUE;
|
|
m_bConvErr = FALSE;
|
|
m_hFileName = NULL;
|
|
m_bUseOEM = TRUE;
|
|
|
|
#ifndef _X86_
|
|
|
|
//Prevent known alignment exception problems in write converter
|
|
//from crashing the app on some RISC machines
|
|
|
|
m_uPrevErrMode = SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT);
|
|
|
|
#endif
|
|
|
|
// Safe to call LoadLibrary - this should be a fully-qualified pathname.
|
|
m_hLibCnv = LoadLibrary(pszLibName);
|
|
|
|
if (NULL != m_hLibCnv)
|
|
{
|
|
LoadFunctions();
|
|
ASSERT(m_pInitConverter != NULL);
|
|
if (m_pInitConverter != NULL)
|
|
{
|
|
//
|
|
// For the current converters, you have to pass a *static*
|
|
// string to InitConverter32
|
|
//
|
|
|
|
VERIFY(m_pInitConverter(AfxGetMainWnd()->GetSafeHwnd(), "WORDPAD"));
|
|
}
|
|
|
|
if (m_pRegisterApp != NULL)
|
|
{
|
|
NegotiateForNonOEM();
|
|
}
|
|
}
|
|
}
|
|
|
|
CConverter::~CConverter()
|
|
{
|
|
if (!m_bDone) // converter thread hasn't exited
|
|
{
|
|
m_bDone = TRUE;
|
|
|
|
if (!m_bForeignToRtf)
|
|
WaitForConverter();
|
|
|
|
m_nBytesAvail = 0;
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
m_nBytesAvail = 0;
|
|
SetEvent(m_hEventConv);
|
|
WaitForConverter();// wait for DoConversion exit
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
}
|
|
|
|
if (m_hEventFile != NULL)
|
|
VERIFY(CloseHandle(m_hEventFile));
|
|
if (m_hEventConv != NULL)
|
|
VERIFY(CloseHandle(m_hEventConv));
|
|
if (m_hLibCnv != NULL)
|
|
FreeLibrary(m_hLibCnv);
|
|
if (m_hFileName != NULL)
|
|
GlobalFree(m_hFileName);
|
|
|
|
#ifndef _X86_
|
|
|
|
//Reset error mode to what it was before we changed it in
|
|
//the constructor
|
|
|
|
SetErrorMode(m_uPrevErrMode);
|
|
|
|
#endif
|
|
}
|
|
|
|
void CConverter::WaitForConverter()
|
|
{
|
|
// while event not signalled -- process messages
|
|
while (MsgWaitForMultipleObjects(1, &m_hEventFile, FALSE, INFINITE,
|
|
QS_SENDMESSAGE) != WAIT_OBJECT_0)
|
|
{
|
|
MSG msg;
|
|
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CConverter::WaitForBuffer()
|
|
{
|
|
// while event not signalled -- process messages
|
|
while (MsgWaitForMultipleObjects(1, &m_hEventConv, FALSE, INFINITE,
|
|
QS_SENDMESSAGE) != WAIT_OBJECT_0)
|
|
{
|
|
MSG msg;
|
|
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
UINT AFX_CDECL CConverter::ConverterThread(LPVOID) // AFX_CDECL added by t-stefb
|
|
{
|
|
ASSERT(m_pThis != NULL);
|
|
|
|
#if defined(_DEBUG)
|
|
HRESULT hRes = OleInitialize(NULL);
|
|
ASSERT(hRes == S_OK || hRes == S_FALSE);
|
|
#else
|
|
OleInitialize(NULL);
|
|
#endif
|
|
|
|
m_pThis->DoConversion();
|
|
OleUninitialize();
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL CConverter::IsFormatCorrect(LPCWSTR pszFileName)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
if (m_hLibCnv == NULL || m_pIsFormatCorrect == NULL)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
char buf[_MAX_PATH];
|
|
if (WideCharToMultiByte(CP_ACP, 0, pszFileName, -1, buf, ARRAYSIZE(buf), NULL, NULL))
|
|
{
|
|
if (m_bUseOEM)
|
|
CharToOemA(buf, buf);
|
|
|
|
HGLOBAL hFileName = StringToHGLOBAL(buf);
|
|
HGLOBAL hDesc = GlobalAlloc(GHND, 256);
|
|
if (NULL == hDesc)
|
|
AfxThrowMemoryException();
|
|
int nRet = m_pIsFormatCorrect(hFileName, hDesc);
|
|
GlobalFree(hDesc);
|
|
GlobalFree(hFileName);
|
|
bRet = (nRet == 1) ? TRUE : FALSE;
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
// static callback function
|
|
int CALLBACK CConverter::WriteOutStatic(int cch, int nPercentComplete)
|
|
{
|
|
ASSERT(m_pThis != NULL);
|
|
return m_pThis->WriteOut(cch, nPercentComplete);
|
|
}
|
|
|
|
int CALLBACK CConverter::WriteOut(int cch, int nPercentComplete)
|
|
{
|
|
ASSERT(m_hBuff != NULL);
|
|
m_nPercent = nPercentComplete;
|
|
if (m_hBuff == NULL)
|
|
return -9;
|
|
|
|
//
|
|
// If m_bDone is TRUE that means the richedit control has stopped
|
|
// streaming in text and is trying to destroy the CConverter object but
|
|
// the converter still has more data to give
|
|
//
|
|
|
|
if (m_bDone)
|
|
{
|
|
ASSERT(!"Richedit control stopped streaming prematurely");
|
|
AfxMessageBox(IDS_CONVERTER_ABORTED);
|
|
return -9;
|
|
}
|
|
|
|
if (cch != 0)
|
|
{
|
|
WaitForBuffer();
|
|
VERIFY(ResetEvent(m_hEventConv));
|
|
m_nBytesAvail = cch;
|
|
SetEvent(m_hEventFile);
|
|
WaitForBuffer();
|
|
}
|
|
return 0; //everything OK
|
|
}
|
|
|
|
int CALLBACK CConverter::ReadInStatic(int /*flags*/, int nPercentComplete)
|
|
{
|
|
ASSERT(m_pThis != NULL);
|
|
return m_pThis->ReadIn(nPercentComplete);
|
|
}
|
|
|
|
int CALLBACK CConverter::ReadIn(int /*nPercentComplete*/)
|
|
{
|
|
ASSERT(m_hBuff != NULL);
|
|
if (m_hBuff == NULL)
|
|
return -8;
|
|
|
|
SetEvent(m_hEventFile);
|
|
WaitForBuffer();
|
|
VERIFY(ResetEvent(m_hEventConv));
|
|
|
|
return m_nBytesAvail;
|
|
}
|
|
|
|
BOOL CConverter::DoConversion()
|
|
{
|
|
USES_CONVERSION;
|
|
m_nLastPercent = -1;
|
|
// m_dwLength = 0; // prevent Read/Write from displaying
|
|
m_nPercent = 0;
|
|
|
|
ASSERT(m_hBuff != NULL);
|
|
ASSERT(m_pThis != NULL);
|
|
HGLOBAL hDesc = StringToHGLOBAL("");
|
|
HGLOBAL hSubset = StringToHGLOBAL("");
|
|
|
|
int nRet = -1;
|
|
if (m_bForeignToRtf && NULL != m_pForeignToRtf)
|
|
{
|
|
ASSERT(m_pForeignToRtf != NULL);
|
|
ASSERT(m_hFileName != NULL);
|
|
nRet = m_pForeignToRtf(m_hFileName, NULL, m_hBuff, hDesc, hSubset,
|
|
(LPFNOUT)WriteOutStatic);
|
|
// wait for next CConverter::Read to come through
|
|
WaitForBuffer();
|
|
VERIFY(ResetEvent(m_hEventConv));
|
|
}
|
|
else if (!m_bForeignToRtf && NULL != m_pRtfToForeign)
|
|
{
|
|
ASSERT(m_pRtfToForeign != NULL);
|
|
ASSERT(m_hFileName != NULL);
|
|
nRet = m_pRtfToForeign(m_hFileName, NULL, m_hBuff, hDesc,
|
|
(LPFNIN)ReadInStatic);
|
|
// don't need to wait for m_hEventConv
|
|
}
|
|
|
|
GlobalFree(hDesc);
|
|
GlobalFree(hSubset);
|
|
if (m_pBuf != NULL)
|
|
GlobalUnlock(m_hBuff);
|
|
GlobalFree(m_hBuff);
|
|
|
|
if (nRet != 0)
|
|
m_bConvErr = TRUE;
|
|
|
|
m_bDone = TRUE;
|
|
m_nPercent = 100;
|
|
m_nLastPercent = -1;
|
|
|
|
SetEvent(m_hEventFile);
|
|
|
|
return (nRet == 0);
|
|
}
|
|
|
|
void CConverter::LoadFunctions()
|
|
{
|
|
m_pInitConverter = (PINITCONVERTER)GetProcAddress(m_hLibCnv, "InitConverter32");
|
|
m_pIsFormatCorrect = (PISFORMATCORRECT)GetProcAddress(m_hLibCnv, "IsFormatCorrect32");
|
|
m_pForeignToRtf = (PFOREIGNTORTF)GetProcAddress(m_hLibCnv, "ForeignToRtf32");
|
|
m_pRtfToForeign = (PRTFTOFOREIGN)GetProcAddress(m_hLibCnv, "RtfToForeign32");
|
|
m_pRegisterApp = (PREGISTERAPP) GetProcAddress(m_hLibCnv, "RegisterApp");
|
|
}
|
|
#endif // #ifdef CONVERTERS
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CConverter::Open(LPCWSTR pszFileName, UINT nOpenFlags,
|
|
CFileException* pException)
|
|
{
|
|
USES_CONVERSION;
|
|
BOOL bRet;
|
|
// The converters only speak ansi
|
|
char buf[_MAX_PATH];
|
|
if (WideCharToMultiByte(CP_ACP, 0, pszFileName, -1, buf, ARRAYSIZE(buf), NULL, NULL))
|
|
{
|
|
if (m_bUseOEM)
|
|
CharToOemA(buf, buf);
|
|
|
|
// let's make sure we could do what is wanted directly even though we aren't
|
|
m_bCloseOnDelete = FALSE;
|
|
m_hFile = (UINT_PTR)hFileNull;
|
|
|
|
BOOL bOpen = CFile::Open(pszFileName, nOpenFlags, pException);
|
|
CFile::Close();
|
|
if (!bOpen)
|
|
return FALSE;
|
|
|
|
m_bForeignToRtf = !(nOpenFlags & (CFile::modeReadWrite | CFile::modeWrite));
|
|
|
|
// check for reading empty file
|
|
if (m_bForeignToRtf)
|
|
{
|
|
CFileStatus _stat;
|
|
if (CFile::GetStatus(pszFileName, _stat) && _stat.m_size == 0)
|
|
return TRUE;
|
|
}
|
|
|
|
//create the events
|
|
m_hEventFile = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_hEventConv = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
//create the converter thread and create the events
|
|
|
|
ASSERT(m_hFileName == NULL);
|
|
m_hFileName = StringToHGLOBAL(buf);
|
|
|
|
m_pThis = this;
|
|
m_bDone = FALSE;
|
|
m_hBuff = GlobalAlloc(GHND, BUFFSIZE);
|
|
ASSERT(m_hBuff != NULL);
|
|
|
|
AfxBeginThread(ConverterThread, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL);
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
// m_hEventConv -- the main thread signals this event when ready for more data
|
|
// m_hEventFile -- the converter signals this event when data is ready
|
|
|
|
UINT CConverter::Read(void FAR* lpBuf, UINT nCount)
|
|
{
|
|
ASSERT(m_bForeignToRtf);
|
|
if (m_bDone)
|
|
return 0;
|
|
// if converter is done
|
|
int cch = nCount;
|
|
BYTE* pBuf = (BYTE*)lpBuf;
|
|
while (cch != 0)
|
|
{
|
|
if (m_nBytesAvail == 0)
|
|
{
|
|
if (m_pBuf != NULL)
|
|
GlobalUnlock(m_hBuff);
|
|
m_pBuf = NULL;
|
|
SetEvent(m_hEventConv);
|
|
WaitForConverter();
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
if (m_bConvErr)
|
|
AfxThrowFileException(CFileException::generic);
|
|
if (m_bDone)
|
|
return nCount - cch;
|
|
m_pBuf = (BYTE*)GlobalLock(m_hBuff);
|
|
ASSERT(m_pBuf != NULL);
|
|
}
|
|
int nBytes = min(cch, m_nBytesAvail);
|
|
memcpy(pBuf, m_pBuf, nBytes);
|
|
pBuf += nBytes;
|
|
m_pBuf += nBytes;
|
|
m_nBytesAvail -= nBytes;
|
|
cch -= nBytes;
|
|
OutputPercent(m_nPercent);
|
|
}
|
|
return nCount - cch;
|
|
}
|
|
|
|
void CConverter::Write(const void FAR* lpBuf, UINT nCount)
|
|
{
|
|
ASSERT(!m_bForeignToRtf);
|
|
|
|
m_nBytesWritten += nCount;
|
|
while (nCount != 0)
|
|
{
|
|
WaitForConverter();
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
if (m_bConvErr)
|
|
AfxThrowFileException(CFileException::generic);
|
|
m_nBytesAvail = min(nCount, BUFFSIZE);
|
|
nCount -= m_nBytesAvail;
|
|
BYTE* pBuf = (BYTE*)GlobalLock(m_hBuff);
|
|
ASSERT(pBuf != NULL);
|
|
memcpy(pBuf, lpBuf, m_nBytesAvail);
|
|
GlobalUnlock(m_hBuff);
|
|
SetEvent(m_hEventConv);
|
|
}
|
|
OutputString(m_strSaving);
|
|
}
|
|
|
|
LONG CConverter::Seek(LONG lOff, UINT nFrom)
|
|
{
|
|
if (lOff != 0 && nFrom != current)
|
|
AfxThrowNotSupportedException();
|
|
return 0;
|
|
}
|
|
|
|
DWORD CConverter::GetPosition() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void CConverter::Flush()
|
|
{
|
|
}
|
|
|
|
void CConverter::Close()
|
|
{
|
|
if (!m_bDone) // converter thread hasn't exited
|
|
{
|
|
m_bDone = TRUE;
|
|
|
|
if (!m_bForeignToRtf)
|
|
WaitForConverter();
|
|
|
|
m_nBytesAvail = 0;
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
m_nBytesAvail = 0;
|
|
SetEvent(m_hEventConv);
|
|
WaitForConverter();// wait for DoConversion exit
|
|
VERIFY(ResetEvent(m_hEventFile));
|
|
}
|
|
|
|
if (m_bConvErr)
|
|
AfxThrowFileException(CFileException::generic);
|
|
}
|
|
|
|
void CConverter::Abort()
|
|
{
|
|
}
|
|
|
|
DWORD CConverter::GetLength() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
return 1;
|
|
}
|
|
|
|
CFile* CConverter::Duplicate() const
|
|
{
|
|
AfxThrowNotSupportedException();
|
|
return NULL;
|
|
}
|
|
|
|
void CConverter::LockRange(DWORD, DWORD)
|
|
{
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
void CConverter::UnlockRange(DWORD, DWORD)
|
|
{
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
void CConverter::SetLength(DWORD)
|
|
{
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: CConverter::NegotiateForNonOEM
|
|
//
|
|
// Synopsis: Try to tell the converter not to expect OEM filenames
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: void
|
|
//
|
|
// Notes: The converter's RegisterApp function will return a handle
|
|
// containing it's preferences (what it supports). The
|
|
// data structure is a 16-bit size and then a sequence of
|
|
// records. For each record the first byte is the size, the
|
|
// second is the "opcode", and then some variable-length opcode
|
|
// specific data. All sizes are inclusive.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void CConverter::NegotiateForNonOEM()
|
|
{
|
|
ASSERT(NULL != m_pRegisterApp);
|
|
|
|
HGLOBAL hPrefs;
|
|
BYTE *pPrefs;
|
|
__int16 cbPrefs;
|
|
|
|
//
|
|
// Tell the converter we don't want to use OEM
|
|
//
|
|
|
|
hPrefs = (*m_pRegisterApp)(fRegAppSupportNonOem, NULL);
|
|
|
|
if (NULL == hPrefs)
|
|
return;
|
|
|
|
pPrefs = (BYTE *) GlobalLock(hPrefs);
|
|
|
|
if (NULL == pPrefs)
|
|
{
|
|
ASSERT(!"GlobalLock failed");
|
|
GlobalFree(hPrefs);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Parse the returned structure looking for a RegAppOpcodeCharset opcode.
|
|
// The argument for this opcode should be either ANSI_CHARSET or
|
|
// OEM_CHARSET. If its ANSI_CHARSET then we can talk Ansi otherwise were
|
|
// stuck with OEM.
|
|
//
|
|
|
|
cbPrefs = (__int16) ((* (__int16 *) pPrefs) - sizeof(cbPrefs));
|
|
pPrefs += sizeof(cbPrefs);
|
|
|
|
while (cbPrefs > 0)
|
|
{
|
|
if (RegAppOpcodeCharset == pPrefs[1])
|
|
{
|
|
ASSERT(ANSI_CHARSET == pPrefs[2] || OEM_CHARSET == pPrefs[2]);
|
|
|
|
m_bUseOEM = (OEM_CHARSET == pPrefs[2]);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (pPrefs[0] <= 0)
|
|
{
|
|
ASSERT(!"RegisterApp is returning bogus data");
|
|
break;
|
|
}
|
|
|
|
cbPrefs = (__int16) (cbPrefs - pPrefs[0]);
|
|
pPrefs += pPrefs[0];
|
|
}
|
|
}
|
|
|
|
GlobalUnlock(pPrefs);
|
|
GlobalFree(hPrefs);
|
|
}
|