Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

884 lines
24 KiB

/**************************************************************************\
* Module Name: context.c
*
* Copyright (c) Microsoft Corp. 1995 All Rights Reserved
*
* Context management routines for imm32 dll
*
* History:
* 03-Jan-1996 wkwok Created
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define IMCC_ALLOC_TOOLARGE 0x1000
/***************************************************************************\
* ImmCreateDefaultContext (Internal: Callback from Win32K.SYS)
*
* Create client side input context sturcture for a given hImc
*
* History:
* 31-Jan-1996 wkwok Created
\***************************************************************************/
BOOL WINAPI ImmCreateDefaultContext(
HIMC hImc)
{
PCLIENTIMC pClientImc;
/*
* ImmLockClientImc() will create client side Imc.
*/
pClientImc = ImmLockClientImc(hImc);
if (pClientImc != NULL) {
/*
* Marks with default input context signature.
*/
SetICF(pClientImc, IMCF_DEFAULTIMC);
ImmUnlockClientImc(pClientImc);
}
/*
* Load up the IME DLL of current keyboard layout.
*/
ImmLoadIME(GetKeyboardLayout(0));
return (pClientImc != NULL);
}
/**************************************************************************\
* ImmCreateContext
*
* Creates and initializes an input context.
*
* 17-Jan-1996 wkwok Created
\**************************************************************************/
HIMC WINAPI ImmCreateContext(void)
{
PCLIENTIMC pClientImc;
HIMC hImc = NULL_HIMC;
pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
if (pClientImc != NULL) {
hImc = NtUserCreateInputContext((DWORD)pClientImc);
if (hImc == NULL_HIMC) {
ImmLocalFree(pClientImc);
return NULL_HIMC;
}
InitImcCrit(pClientImc);
pClientImc->hImc = hImc;
}
return hImc;
}
/**************************************************************************\
* ImmDestroyContext
*
* Destroys an input context.
*
* 17-Jan-1996 wkwok Created
\**************************************************************************/
BOOL WINAPI ImmDestroyContext(
HIMC hImc)
{
return DestroyInputContext(hImc, GetKeyboardLayout(0));
}
/**************************************************************************\
* ImmAssociateContext
*
* Associates an input context to the specified window handle.
*
* 17-Jan-1996 wkwok Created
\**************************************************************************/
HIMC WINAPI ImmAssociateContext(
HWND hWnd,
HIMC hImc)
{
PWND pWnd;
HIMC hPrevImc, hDefImc;
PINPUTCONTEXT pInputContext;
if ((pWnd = ValidateHwnd(hWnd)) == (PWND)NULL) {
RIPMSG1(RIP_WARNING,
"ImmAssociateContext: invalid window handle %x", hWnd);
return NULL_HIMC;
}
/*
* associate to the same input context, do nothing.
*/
if (pWnd->hImc == hImc)
return hImc;
hPrevImc = NtUserAssociateInputContext(hWnd, hImc);
if (hPrevImc == NULL_HIMC)
return hPrevImc;
hDefImc = (HIMC)NtUserQueryWindow(hWnd, WindowDefaultInputContext);
/*
* Update the hPrevImc if it is not the default IMC.
*/
if (hDefImc != hPrevImc) {
pInputContext = ImmLockIMC(hPrevImc);
if (pInputContext != NULL) {
pInputContext->hWnd = NULL;
ImmUnlockIMC(hPrevImc);
}
}
if (GetFocus() == hWnd) {
ImmSetActiveContext(hWnd, hPrevImc, FALSE);
ImmSetActiveContext(hWnd, hImc, TRUE);
}
return hPrevImc;
}
/**************************************************************************\
* ImmGetContext
*
* Retrieves the input context that is associated to the given window.
*
* 17-Jan-1996 wkwok Created
\**************************************************************************/
HIMC WINAPI ImmGetContext(
HWND hWnd)
{
PWND pwnd;
if ((pwnd = ValidateHwnd(hWnd)) == (PWND)NULL) {
RIPMSG1(RIP_WARNING,
"ImmGetContext: invalid window handle %x", hWnd);
return NULL_HIMC;
}
/*
* Don't allow other process to access input context
*/
if (!TestWindowProcess(pwnd)) {
RIPMSG0(RIP_WARNING,
"ImmGetContext: can not get input context of other process");
return NULL_HIMC;
}
return pwnd->hImc;
}
/**************************************************************************\
* ImmGetSaveContext
*
* Retrieves the input context that is associated to the given window.
*
* 15-Mar-1996 wkwok Created
\**************************************************************************/
HIMC ImmGetSaveContext(
HWND hWnd,
DWORD dwFlag)
{
HIMC hRetImc;
PCLIENTIMC pClientImc;
if (hWnd == NULL) {
/*
* Retrieves the default input context of current thread.
*/
hRetImc = NtUserGetThreadState(UserThreadStateDefaultInputContext);
}
else {
/*
* Retrieves the input context associated to the given window.
*/
hRetImc = ImmGetContext(hWnd);
if (hRetImc == NULL_HIMC && (dwFlag & IGSC_DEFIMCFALLBACK)) {
/*
* hWnd associated with NULL input context, retrieves the
* default input context of the hWnd's creator thread.
*/
hRetImc = (HIMC)NtUserQueryWindow(hWnd, WindowDefaultInputContext);
}
}
pClientImc = ImmLockClientImc(hRetImc);
if (pClientImc == NULL)
return NULL_HIMC;
if ((dwFlag & IGSC_WINNLSCHECK) && TestICF(pClientImc, IMCF_WINNLSDISABLE))
hRetImc = NULL_HIMC;
ImmUnlockClientImc(pClientImc);
return hRetImc;
}
/**************************************************************************\
* ImmReleaseContext
*
* Releases the input context retrieved by ImmGetContext().
*
* 17-Jan-1996 wkwok Created
\**************************************************************************/
BOOL WINAPI ImmReleaseContext(
HWND hWnd,
HIMC hImc)
{
return TRUE;
}
/**************************************************************************\
* ImmSetActiveContext
*
* 15-Mar-1996 wkwok Created
\**************************************************************************/
BOOL ImmSetActiveContext(
HWND hWnd,
HIMC hImc,
BOOL fActivate)
{
PCLIENTIMC pClientImc;
PINPUTCONTEXT pInputContext;
PIMEDPI pImeDpi;
DWORD dwISC;
HIMC hSaveImc;
HWND hDefImeWnd;
#ifdef DEBUG
PWND pWnd = ValidateHwnd(hWnd);
if (pWnd != NULL && GETPTI(pWnd) != PtiCurrent()) {
RIPMSG1(RIP_WARNING, "hWnd (=%lx) is not of current thread.", hWnd);
}
#endif
dwISC = ISC_SHOWUIALL;
pClientImc = ImmLockClientImc(hImc);
if (!fActivate) {
if (pClientImc != NULL)
ClrICF(pClientImc, IMCF_ACTIVE);
goto NotifySetActive;
}
if (hImc == NULL_HIMC) {
hSaveImc = ImmGetSaveContext(hWnd, 0);
pInputContext = ImmLockIMC(hSaveImc);
if (pInputContext != NULL) {
pInputContext->hWnd = hWnd;
ImmUnlockIMC(hSaveImc);
}
goto NotifySetActive;
}
/*
* Non-NULL input context, window handle have to be updated.
*/
if (pClientImc == NULL)
return FALSE;
pInputContext = ImmLockIMC(hImc);
if (pInputContext == NULL) {
ImmUnlockClientImc(pClientImc);
return FALSE;
}
pInputContext->hWnd = hWnd;
SetICF(pClientImc, IMCF_ACTIVE);
#ifdef LATER
// Do uNumLangVKey checking later
#endif
if (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN)
dwISC = ISC_SHOWUIALL - ISC_SHOWUICOMPOSITIONWINDOW;
ImmUnlockIMC(hImc);
NotifySetActive:
if (hImc != NULL_HIMC) {
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(0));
if (pImeDpi != NULL) {
(*pImeDpi->pfn.ImeSetActiveContext)(hImc, fActivate);
ImmUnlockImeDpi(pImeDpi);
}
}
/*
* Notify UI
*/
if (IsWindow(hWnd)) {
SendMessage(hWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
}
else if (!fActivate) {
/*
* Because hWnd is not there (maybe destroyed), we send
* WM_IME_SETCONTEXT to the default IME window.
*/
if ((hDefImeWnd = ImmGetDefaultIMEWnd(NULL)) != NULL) {
SendMessage(hDefImeWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
}
else {
RIPMSG0(RIP_WARNING,
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(FALSE).");
}
}
#ifdef DEBUG
else {
RIPMSG0(RIP_WARNING,
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(TRUE).");
}
#endif
#ifdef LATER
// Implements ProcessIMCEvent() later.
#endif
if (pClientImc != NULL)
ImmUnlockClientImc(pClientImc);
return TRUE;
}
/**************************************************************************\
* CreateInputContext
*
* 20-Feb-1996 wkwok Created
\**************************************************************************/
BOOL CreateInputContext(
HIMC hImc,
HKL hKL)
{
PIMEDPI pImeDpi;
PCLIENTIMC pClientImc;
DWORD dwPrivateDataSize;
DWORD fdwInitConvMode = 0; // do it later
BOOL fInitOpen = FALSE; // do it later
PINPUTCONTEXT pInputContext;
PCOMPOSITIONSTRING pCompStr;
PCANDIDATEINFO pCandInfo;
PGUIDELINE pGuideLine;
int i;
pInputContext = ImmLockIMC(hImc);
if (!pInputContext) {
RIPMSG1(RIP_WARNING, "CreateContext: Lock hIMC %x failure", hImc);
goto CrIMCLockErrOut;
}
/*
* Initialize the member of INPUTCONTEXT
*/
pInputContext->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
if (!pInputContext->hCompStr) {
RIPMSG0(RIP_WARNING, "CreateContext: Create hCompStr failure");
goto CrIMCUnlockIMC;
}
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
if (!pCompStr) {
RIPMSG1(RIP_WARNING,
"CreateContext: Lock hCompStr %x failure", pInputContext->hCompStr);
goto CrIMCFreeCompStr;
}
pCompStr->dwSize = sizeof(COMPOSITIONSTRING);
ImmUnlockIMCC(pInputContext->hCompStr);
pInputContext->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
if (!pInputContext->hCandInfo) {
RIPMSG0(RIP_WARNING, "CreateContext: Create hCandInfo failure");
goto CrIMCFreeCompStr;
}
pCandInfo = (PCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
if (!pCandInfo) {
RIPMSG1(RIP_WARNING,
"CreateContext: Lock hCandInfo %x failure", pInputContext->hCandInfo);
goto CrIMCFreeCandInfo;
}
pCandInfo->dwSize = sizeof(CANDIDATEINFO);
ImmUnlockIMCC(pInputContext->hCandInfo);
pInputContext->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
if (!pInputContext->hGuideLine) {
RIPMSG0(RIP_WARNING, "CreateContext: Create hGuideLine failure");
goto CrIMCFreeCandInfo;
}
pGuideLine = (PGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
if (!pGuideLine) {
RIPMSG1(RIP_WARNING,
"CreateContext: Lock hGuideLine %x failure", pInputContext->hGuideLine);
goto CrIMCFreeGuideLine;
}
pGuideLine->dwSize = sizeof(GUIDELINE);
ImmUnlockIMCC(pInputContext->hGuideLine);
pInputContext->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
if (!pInputContext->hMsgBuf) {
RIPMSG0(RIP_WARNING, "CreateContext: Create hMsgBuf failure");
goto CrIMCFreeGuideLine;
}
pInputContext->dwNumMsgBuf = 0;
pInputContext->fOpen = fInitOpen;
pInputContext->fdwConversion = fdwInitConvMode;
for (i = 0; i < 4; i++) {
pInputContext->cfCandForm[i].dwIndex = (DWORD)(-1);
}
pImeDpi = ImmLockImeDpi(hKL);
if (pImeDpi != NULL) {
if ((pClientImc = ImmLockClientImc(hImc)) == NULL) {
RIPMSG0(RIP_WARNING, "CreateContext: ImmLockClientImc() failure");
ImmUnlockImeDpi(pImeDpi);
goto CrIMCFreeMsgBuf;
}
/*
* Unicode based IME expects an Uncode based input context.
*/
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
SetICF(pClientImc, IMCF_UNICODE);
ImmUnlockClientImc(pClientImc);
dwPrivateDataSize = pImeDpi->ImeInfo.dwPrivateDataSize;
}
else {
dwPrivateDataSize = sizeof(UINT);
}
pInputContext->hPrivate = ImmCreateIMCC(dwPrivateDataSize);
if (!pInputContext->hPrivate) {
RIPMSG0(RIP_WARNING, "CreateContext: Create hPrivate failure");
ImmUnlockImeDpi(pImeDpi);
goto CrIMCFreeMsgBuf;
}
if (pImeDpi != NULL) {
(*pImeDpi->pfn.ImeSelect)(hImc, TRUE);
ImmUnlockImeDpi(pImeDpi);
}
ImmUnlockIMC(hImc);
return TRUE;
/*
* context failure case
*/
CrIMCFreeMsgBuf:
ImmDestroyIMCC(pInputContext->hMsgBuf);
CrIMCFreeGuideLine:
ImmDestroyIMCC(pInputContext->hGuideLine);
CrIMCFreeCandInfo:
ImmDestroyIMCC(pInputContext->hCandInfo);
CrIMCFreeCompStr:
ImmDestroyIMCC(pInputContext->hCompStr);
CrIMCUnlockIMC:
ImmUnlockIMC(hImc);
CrIMCLockErrOut:
return FALSE;
}
/**************************************************************************\
* DestroyInputContext
*
* 20-Feb-1996 wkwok Created
\**************************************************************************/
BOOL DestroyInputContext(
HIMC hImc,
HKL hKL)
{
PINPUTCONTEXT pInputContext;
PIMEDPI pImeDpi;
PIMC pImc;
PCLIENTIMC pClientImc;
if (hImc == NULL_HIMC)
return FALSE;
pImc = HMValidateHandle((HANDLE)hImc, TYPE_INPUTCONTEXT);
/*
* Cannot destroy input context from other thread.
*/
if (pImc == NULL || GETPTI(pImc) != PtiCurrent())
return FALSE;
/*
* We are destroying this hImc and we don't bother
* to lock its pClientImc.
*/
pClientImc = (PCLIENTIMC)pImc->dwClientImcData;
if (pClientImc == NULL) {
/*
* Client side Imc has not been initialzed yet.
* We simply destroy this input context from kernel.
*/
return NtUserDestroyInputContext(hImc);
}
if (TestICF(pClientImc, IMCF_DEFAULTIMC)) {
/*
* Cannot destroy default input context.
*/
return FALSE;
}
if (TestICF(pClientImc, IMCF_INDESTROY)) {
/*
* This hImc is being destroyed. Returns as success.
*/
return TRUE;
}
pInputContext = ImmLockIMC(hImc);
if (!pInputContext) {
RIPMSG1(RIP_WARNING, "DestroyContext: Lock hImc %x failure", hImc);
return FALSE;
}
pImeDpi = ImmLockImeDpi(hKL);
if (pImeDpi != NULL) {
(*pImeDpi->pfn.ImeSelect)(hImc, FALSE);
ImmUnlockImeDpi(pImeDpi);
}
SetICF(pClientImc, IMCF_INDESTROY);
ImmDestroyIMCC(pInputContext->hPrivate);
ImmDestroyIMCC(pInputContext->hMsgBuf);
ImmDestroyIMCC(pInputContext->hGuideLine);
ImmDestroyIMCC(pInputContext->hCandInfo);
ImmDestroyIMCC(pInputContext->hCompStr);
ImmUnlockIMC(hImc);
return NtUserDestroyInputContext(hImc);
}
/**************************************************************************\
* SelectInputContext
*
* 20-Feb-1996 wkwok Created
\**************************************************************************/
VOID SelectInputContext(
HKL hSelKL,
HKL hUnSelKL,
HIMC hImc)
{
PIMEDPI pSelImeDpi, pUnSelImeDpi;
PCLIENTIMC pClientImc;
PINPUTCONTEXT pInputContext;
DWORD dwSelPriv = 0, dwUnSelPriv = 0, dwSize;
HIMCC hImcc;
PCOMPOSITIONSTRING pCompStr;
PCANDIDATEINFO pCandInfo;
PGUIDELINE pGuideLine;
BOOL fLogFontInited;
pClientImc = ImmLockClientImc(hImc);
if (pClientImc == NULL)
return;
pSelImeDpi = ImmLockImeDpi(hSelKL);
pUnSelImeDpi = ImmLockImeDpi(hUnSelKL);
/*
* According to private memory size of the two layout, we decide
* whether we nee to reallocate this memory block
*/
if (pSelImeDpi != NULL)
dwSelPriv = pSelImeDpi->ImeInfo.dwPrivateDataSize;
if (pUnSelImeDpi != NULL)
dwUnSelPriv = pUnSelImeDpi->ImeInfo.dwPrivateDataSize;
dwSelPriv = max(dwSelPriv, sizeof(UINT));
dwUnSelPriv = max(dwUnSelPriv, sizeof(UINT));
/*
* Unselect the input context.
*/
if (pUnSelImeDpi != NULL)
(*pUnSelImeDpi->pfn.ImeSelect)(hImc, FALSE);
/*
* Reinitialize the client side input context for the selected layout.
*/
if ((pInputContext = ImmLockIMC(hImc)) != NULL) {
fLogFontInited = ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT);
if (TestICF(pClientImc, IMCF_UNICODE) && pSelImeDpi != NULL &&
!(pSelImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
/*
* Check if there is any LOGFONT to be converted.
*/
if (fLogFontInited) {
LOGFONTA LogFontA;
LFontWtoLFontA(&pInputContext->lfFont.W, &LogFontA);
RtlCopyMemory(&pInputContext->lfFont.A, &LogFontA, sizeof(LOGFONTA));
}
ClrICF(pClientImc, IMCF_UNICODE);
}
else if (!TestICF(pClientImc, IMCF_UNICODE) && pSelImeDpi != NULL &&
(pSelImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
/*
* Check if there is any LOGFONT to be converted.
*/
if (fLogFontInited) {
LOGFONTW LogFontW;
LFontAtoLFontW(&pInputContext->lfFont.A, &LogFontW);
RtlCopyMemory(&pInputContext->lfFont.W, &LogFontW, sizeof(LOGFONTW));
}
SetICF(pClientImc, IMCF_UNICODE);
}
/*
* hPrivate
*/
if (dwUnSelPriv != dwSelPriv) {
hImcc = ImmReSizeIMCC(pInputContext->hPrivate, dwSelPriv);
if (hImcc) {
pInputContext->hPrivate = hImcc;
}
else {
RIPMSG1(RIP_WARNING,
"SelectContext: resize hPrivate %lX failure",
pInputContext->hPrivate);
ImmDestroyIMCC(pInputContext->hPrivate);
pInputContext->hPrivate = ImmCreateIMCC(dwSelPriv);
}
}
/*
* hMsgBuf
*/
dwSize = ImmGetIMCCSize(pInputContext->hMsgBuf);
if (ImmGetIMCCLockCount(pInputContext->hMsgBuf) != 0 ||
dwSize > IMCC_ALLOC_TOOLARGE) {
RIPMSG0(RIP_WARNING, "SelectContext: create new hMsgBuf");
ImmDestroyIMCC(pInputContext->hMsgBuf);
pInputContext->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
pInputContext->dwNumMsgBuf = 0;
}
/*
* hGuideLine
*/
dwSize = ImmGetIMCCSize(pInputContext->hGuideLine);
if (ImmGetIMCCLockCount(pInputContext->hGuideLine) != 0 ||
dwSize < sizeof(GUIDELINE) || dwSize > IMCC_ALLOC_TOOLARGE) {
RIPMSG0(RIP_WARNING, "SelectContext: create new hGuideLine");
ImmDestroyIMCC(pInputContext->hGuideLine);
pInputContext->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
pGuideLine = (PGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
if (pGuideLine != NULL) {
pGuideLine->dwSize = sizeof(GUIDELINE);
ImmUnlockIMCC(pInputContext->hGuideLine);
}
}
/*
* hCandInfo
*/
dwSize = ImmGetIMCCSize(pInputContext->hCandInfo);
if (ImmGetIMCCLockCount(pInputContext->hCandInfo) != 0 ||
dwSize < sizeof(CANDIDATEINFO) || dwSize > IMCC_ALLOC_TOOLARGE) {
RIPMSG0(RIP_WARNING, "SelectContext: create new hCandInfo");
ImmDestroyIMCC(pInputContext->hCandInfo);
pInputContext->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
pCandInfo = (PCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
if (pCandInfo != NULL) {
pCandInfo->dwSize = sizeof(CANDIDATEINFO);
ImmUnlockIMCC(pInputContext->hCandInfo);
}
}
/*
* hCompStr
*/
dwSize = ImmGetIMCCSize(pInputContext->hCompStr);
if (ImmGetIMCCLockCount(pInputContext->hCompStr) != 0 ||
dwSize < sizeof(COMPOSITIONSTRING) || dwSize > IMCC_ALLOC_TOOLARGE) {
RIPMSG0(RIP_WARNING, "SelectContext: create new hCompStr");
ImmDestroyIMCC(pInputContext->hCompStr);
pInputContext->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
if (pCompStr != NULL) {
pCompStr->dwSize = sizeof(COMPOSITIONSTRING);
ImmUnlockIMCC(pInputContext->hCompStr);
}
}
ImmUnlockIMC(hImc);
}
/*
* Select the input context.
*/
if (pSelImeDpi != NULL)
(*pSelImeDpi->pfn.ImeSelect)(hImc, TRUE);
ImmUnlockImeDpi(pUnSelImeDpi);
ImmUnlockImeDpi(pSelImeDpi);
ImmUnlockClientImc(pClientImc);
return;
}
/**************************************************************************\
* EnumInputContext
*
* 20-Feb-1996 wkwok Created
\**************************************************************************/
BOOL EnumInputContext(
DWORD idThread,
IMCENUMPROC lpfn,
LONG lParam)
{
UINT i;
UINT cHimc;
HIMC *phimcT;
HIMC *phimcFirst;
BOOL fSuccess = TRUE;
/*
* Get the himc list. It is returned in a block of memory
* allocated with ImmLocalAlloc.
*/
if ((cHimc = BuildHimcList(idThread, &phimcFirst)) == 0) {
return FALSE;
}
/*
* Loop through the input contexts, call the function pointer back for
* each one. End loop if either FALSE is returned or the end-of-list is
* reached.
*/
phimcT = phimcFirst;
for (i = 0; i < cHimc; i++) {
if (RevalidateHimc(*phimcT)) {
if (!(fSuccess = (*lpfn)(*phimcT, lParam)))
break;
}
phimcT++;
}
/*
* Free up buffer and return status - TRUE if entire list was enumerated,
* FALSE otherwise.
*/
ImmLocalFree(phimcFirst);
return fSuccess;
}
/**************************************************************************\
* BuildHimcList
*
* 20-Feb-1996 wkwok Created
\**************************************************************************/
DWORD BuildHimcList(
DWORD idThread,
HIMC **pphimcFirst)
{
UINT cHimc;
HIMC *phimcFirst;
NTSTATUS Status;
int cTries;
/*
* Allocate a buffer to hold the names.
*/
cHimc = 64;
phimcFirst = ImmLocalAlloc(0, cHimc * sizeof(HIMC));
if (phimcFirst == NULL)
return 0;
Status = NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
/*
* If the buffer wasn't big enough, reallocate
* the buffer and try again.
*/
cTries = 0;
while (Status == STATUS_BUFFER_TOO_SMALL) {
ImmLocalFree(phimcFirst);
/*
* If we can't seem to get it right,
* call it quits
*/
if (cTries++ == 10)
return 0;
phimcFirst = ImmLocalAlloc(0, cHimc * sizeof(HIMC));
if (phimcFirst == NULL)
return 0;
Status = NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
}
if (!NT_SUCCESS(Status) || cHimc == 0) {
ImmLocalFree(phimcFirst);
return 0;
}
*pphimcFirst = phimcFirst;
return cHimc;
}