https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3194e320cfd143fa7f3ad4183f8b3305a113b07

commit b3194e320cfd143fa7f3ad4183f8b3305a113b07
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Tue Oct 31 22:45:28 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Tue Oct 31 22:45:28 2023 +0900

    [IMM32][SDK] Add CtfAImmActivate/Deactivate functions (#5835)
    
    - Add dll/win32/imm32/CtfImeTable.h for CTF
      IME functions.
    - Implementing Imm32CheckAndApplyAppCompat,
      Imm32LoadCtfIme, and
      Imm32EnumCreateCtfICProc helper functions.
    - Add CtfAImmActivate and CtfAImmDeactivate
      functions.
    - s/CI_TFSDISABLED/CI_TSFDISABLED/
    CORE-19268
---
 dll/win32/imm32/CtfImeTable.h     |  18 +++
 dll/win32/imm32/ctf.c             | 329 +++++++++++++++++++++++++++++++++++---
 dll/win32/imm32/imm32.spec        |   2 +
 dll/win32/imm32/precomp.h         |   4 +-
 sdk/include/reactos/imm32_undoc.h |   6 +-
 win32ss/include/ntuser.h          |   6 +-
 6 files changed, 334 insertions(+), 31 deletions(-)

diff --git a/dll/win32/imm32/CtfImeTable.h b/dll/win32/imm32/CtfImeTable.h
new file mode 100644
index 00000000000..14f701b6c46
--- /dev/null
+++ b/dll/win32/imm32/CtfImeTable.h
@@ -0,0 +1,18 @@
+/*
+ * PROJECT:     ReactOS IMM32
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Defining the CTF IME file interface
+ * COPYRIGHT:   Copyright 2023 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
+ */
+
+/* The valid CTF IME file contains the following functions: */
+
+/* DEFINE_CTF_IME_FN(func_name, ret_type, params) */
+DEFINE_CTF_IME_FN(CtfImeCreateThreadMgr, HRESULT, (VOID))
+DEFINE_CTF_IME_FN(CtfImeDestroyThreadMgr, HRESULT, (VOID))
+DEFINE_CTF_IME_FN(CtfImeCreateInputContext, HRESULT, (HIMC hIMC))
+DEFINE_CTF_IME_FN(CtfImeDestroyInputContext, HRESULT, (HIMC hIMC))
+DEFINE_CTF_IME_FN(CtfImeSetActiveContextAlways, HRESULT, (DWORD dwFIXME1, 
DWORD dwFIXME2, DWORD dwFIXME3, DWORD dwFIXME4))
+DEFINE_CTF_IME_FN(CtfImeProcessCicHotkey, HRESULT, (DWORD dwFIXME1, DWORD 
dwFIXME2, DWORD dwFIXME3))
+DEFINE_CTF_IME_FN(CtfImeDispatchDefImeMessage, LRESULT, (HWND hWnd, UINT uMsg, 
WPARAM wParam, LPARAM lParam))
+DEFINE_CTF_IME_FN(CtfImeIsIME, BOOL, (HKL hKL))
diff --git a/dll/win32/imm32/ctf.c b/dll/win32/imm32/ctf.c
index 8495725ed0f..eeeae62b588 100644
--- a/dll/win32/imm32/ctf.c
+++ b/dll/win32/imm32/ctf.c
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS IMM32
  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
  * PURPOSE:     Implementing the IMM32 Cicero-aware Text Framework (CTF)
- * COPYRIGHT:   Copyright 2022 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
+ * COPYRIGHT:   Copyright 2022-2023 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
  */
 
 #include "precomp.h"
@@ -17,62 +17,326 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
  * https://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html
  */
 
-// Win: LoadCtfIme
-HMODULE APIENTRY Imm32LoadCtfIme(VOID)
+/*
+ * TSF stands for "Text Services Framework". "Cicero" is the code name of TSF.
+ * CTF stands for "Cicero-aware Text Framework".
+ *
+ * Comparing with old-style IMM IME, the combination of CTF IME and TSF 
provides
+ * new-style and high-level input method.
+ *
+ * The CTF IME file is a DLL file that the software developer distributes.
+ * The export functions of the CTF IME file are defined in "CtfImeTable.h" of
+ * this folder.
+ */
+
+/* The instance of the CTF IME file */
+HINSTANCE g_hCtfIme = NULL;
+
+/* Define the function types (FN_...) for CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+    typedef ret_type (WINAPI *FN_##func_name)params;
+#include "CtfImeTable.h"
+
+/* Define the global variables (g_pfn...) for CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+    FN_##func_name g_pfn##func_name = NULL;
+#include "CtfImeTable.h"
+
+/* The macro that gets the variable name from the CTF IME function name */
+#define CTF_IME_FN(func_name) g_pfn##func_name
+
+/* The type of ApphelpCheckIME function in apphelp.dll */
+typedef BOOL (WINAPI *FN_ApphelpCheckIME)(_In_z_ LPCWSTR AppName);
+
+/* FIXME: This is kernel32 function. We have to declare this in some header. */
+BOOL WINAPI
+BaseCheckAppcompatCache(_In_z_ LPCWSTR ApplicationName,
+                        _In_ HANDLE FileHandle,
+                        _In_opt_z_ LPCWSTR Environment,
+                        _Out_ PULONG pdwReason);
+
+/***********************************************************************
+ * This function checks whether the app's IME is disabled by application
+ * compatibility patcher.
+ */
+BOOL
+Imm32CheckAndApplyAppCompat(
+    _In_ ULONG dwReason,
+    _In_z_ LPCWSTR pszAppName)
 {
-    return NULL;
+    HINSTANCE hinstApphelp;
+    FN_ApphelpCheckIME pApphelpCheckIME;
+
+    /* Query the application compatibility patcher */
+    if (BaseCheckAppcompatCache(pszAppName, INVALID_HANDLE_VALUE, NULL, 
&dwReason))
+        return TRUE; /* The app's IME is not disabled */
+
+    /* Load apphelp.dll if necessary */
+    hinstApphelp = GetModuleHandleW(L"apphelp.dll");
+    if (!hinstApphelp)
+    {
+        hinstApphelp = LoadLibraryW(L"apphelp.dll");
+        if (!hinstApphelp)
+            return TRUE; /* There is no apphelp.dll. The app's IME is not 
disabled */
+    }
+
+    /* Is ApphelpCheckIME implemented? */
+    pApphelpCheckIME = (FN_ApphelpCheckIME)GetProcAddress(hinstApphelp, 
"ApphelpCheckIME");
+    if (!pApphelpCheckIME)
+        return TRUE; /* Not implemented. The app's IME is not disabled */
+
+    /* Is the app's IME disabled or not? */
+    return pApphelpCheckIME(pszAppName);
 }
 
-// Win: Internal_CtfImeDestroyInputContext
-HRESULT APIENTRY Imm32CtfImeDestroyInputContext(HIMC hIMC)
+/***********************************************************************
+ * This function loads the CTF IME file if necessary and establishes
+ * communication with the CTF IME.
+ */
+HINSTANCE
+Imm32LoadCtfIme(VOID)
+{
+    BOOL bSuccess = FALSE;
+    IMEINFOEX ImeInfoEx;
+    WCHAR szImeFile[MAX_PATH];
+
+    /* Lock the IME interface */
+    RtlEnterCriticalSection(&gcsImeDpi);
+
+    do
+    {
+        if (g_hCtfIme) /* Already loaded? */
+        {
+            bSuccess = TRUE;
+            break;
+        }
+
+        /*
+         * NOTE: (HKL)0x04090409 is English US keyboard (default).
+         * The Cicero keyboard logically uses English US keyboard.
+         */
+        if (!ImmLoadLayout((HKL)ULongToHandle(0x04090409), &ImeInfoEx))
+            break;
+
+        /* Build a path string in system32. The installed IME file must be in 
system32. */
+        Imm32GetSystemLibraryPath(szImeFile, _countof(szImeFile), 
ImeInfoEx.wszImeFile);
+
+        /* Is the CTF IME disabled by app compatibility patcher? */
+        if (!Imm32CheckAndApplyAppCompat(0, szImeFile))
+            break; /* This IME is disabled */
+
+        /* Load a CTF IME file */
+        g_hCtfIme = LoadLibraryW(szImeFile);
+        if (!g_hCtfIme)
+            break;
+
+        /* Assume success */
+        bSuccess = TRUE;
+
+        /* Retrieve the CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+        CTF_IME_FN(func_name) = (FN_##func_name)GetProcAddress(g_hCtfIme, 
#func_name); \
+        if (!CTF_IME_FN(func_name)) \
+        { \
+            bSuccess = FALSE; /* Failed */ \
+            break; \
+        }
+#include "CtfImeTable.h"
+    } while (0);
+
+    /* Unload the CTF IME if failed */
+    if (!bSuccess)
+    {
+        /* Set NULL to the function pointers */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) CTF_IME_FN(func_name) = 
NULL;
+#include "CtfImeTable.h"
+
+        if (g_hCtfIme)
+        {
+            FreeLibrary(g_hCtfIme);
+            g_hCtfIme = NULL;
+        }
+    }
+
+    /* Unlock the IME interface */
+    RtlLeaveCriticalSection(&gcsImeDpi);
+
+    return g_hCtfIme;
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeCreateThreadMgr(VOID)
 {
     if (!Imm32LoadCtfIme())
         return E_FAIL;
 
-#if 1
-    FIXME("(%p)\n", hIMC);
-    return E_NOTIMPL;
-#else
-    return g_pfnCtfImeDestroyInputContext(hIMC);
-#endif
+    return CTF_IME_FN(CtfImeCreateThreadMgr)();
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeDestroyThreadMgr(VOID)
+{
+    if (!Imm32LoadCtfIme())
+        return E_FAIL;
+
+    return CTF_IME_FN(CtfImeDestroyThreadMgr)();
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeCreateInputContext(
+    _In_ HIMC hIMC)
+{
+    if (!Imm32LoadCtfIme())
+        return E_FAIL;
+
+    return CTF_IME_FN(CtfImeCreateInputContext)(hIMC);
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeDestroyInputContext(_In_ HIMC hIMC)
+{
+    if (!Imm32LoadCtfIme())
+        return E_FAIL;
+
+    return CTF_IME_FN(CtfImeDestroyInputContext)(hIMC);
+}
+
+/***********************************************************************
+ * The callback function to activate CTF IMEs. Used in CtfAImmActivate.
+ */
+static BOOL CALLBACK
+Imm32EnumCreateCtfICProc(
+    _In_ HIMC hIMC,
+    _In_ LPARAM lParam)
+{
+    UNREFERENCED_PARAMETER(lParam);
+    CtfImeCreateInputContext(hIMC);
+    return TRUE; /* Continue */
 }
 
-// Win: CtfImmTIMDestroyInputContext
-HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC)
+/***********************************************************************
+ * This function calls CtfImeDestroyInputContext if possible.
+ */
+HRESULT
+CtfImmTIMDestroyInputContext(
+    _In_ HIMC hIMC)
 {
     if (!IS_CICERO_MODE() || (GetWin32ClientInfo()->dwCompatFlags2 & 2))
         return E_NOINTERFACE;
 
-    return Imm32CtfImeDestroyInputContext(hIMC);
+    return CtfImeDestroyInputContext(hIMC);
 }
 
-// Win: CtfImmTIMCreateInputContext
-HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC)
+HRESULT
+CtfImmTIMCreateInputContext(
+    _In_ HIMC hIMC)
 {
     TRACE("(%p)\n", hIMC);
     return E_NOTIMPL;
 }
 
+/***********************************************************************
+ *      CtfAImmActivate (IMM32.@)
+ *
+ * This function activates "Active IMM" (AIMM) and TSF.
+ */
+HRESULT WINAPI
+CtfAImmActivate(
+    _Out_opt_ HINSTANCE *phinstCtfIme)
+{
+    HRESULT hr;
+    HINSTANCE hinstCtfIme;
+
+    TRACE("(%p)\n", phinstCtfIme);
+
+    /* Load a CTF IME file if necessary */
+    hinstCtfIme = Imm32LoadCtfIme();
+
+    /* Create a thread manager of the CTF IME */
+    hr = CtfImeCreateThreadMgr();
+    if (hr == S_OK)
+    {
+        /* Update CI_... flags of the thread client info */
+        GetWin32ClientInfo()->CI_flags |= CI_AIMMACTIVATED; /* Activate AIMM */
+        GetWin32ClientInfo()->CI_flags &= ~CI_TSFDISABLED;  /* Enable TSF */
+
+        /* Create the CTF input contexts */
+        ImmEnumInputContext(0, Imm32EnumCreateCtfICProc, 0);
+    }
+
+    if (phinstCtfIme)
+        *phinstCtfIme = hinstCtfIme;
+
+    return hr;
+}
+
+/***********************************************************************
+ *      CtfAImmDeactivate (IMM32.@)
+ *
+ * This function de-activates "Active IMM" (AIMM) and TSF.
+ */
+HRESULT WINAPI
+CtfAImmDeactivate(
+    _In_ BOOL bDestroy)
+{
+    HRESULT hr;
+
+    if (!bDestroy)
+        return E_FAIL;
+
+    hr = CtfImeDestroyThreadMgr();
+    if (hr == S_OK)
+    {
+        GetWin32ClientInfo()->CI_flags &= ~CI_AIMMACTIVATED; /* Deactivate 
AIMM */
+        GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;    /* Disable TSF */
+    }
+
+    return hr;
+}
+
 /***********************************************************************
  *             CtfImmIsCiceroEnabled (IMM32.@)
+ *
+ * @return TRUE if Cicero is enabled.
  */
-BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
+BOOL WINAPI
+CtfImmIsCiceroEnabled(VOID)
 {
     return IS_CICERO_MODE();
 }
 
 /***********************************************************************
  *             CtfImmIsTextFrameServiceDisabled(IMM32.@)
+ *
+ * @return TRUE if TSF is disabled.
  */
-BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
+BOOL WINAPI
+CtfImmIsTextFrameServiceDisabled(VOID)
 {
-    return !!(GetWin32ClientInfo()->CI_flags & CI_TFSDISABLED);
+    return !!(GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED);
 }
 
 /***********************************************************************
  *             CtfImmTIMActivate(IMM32.@)
  */
-HRESULT WINAPI CtfImmTIMActivate(HKL hKL)
+HRESULT WINAPI
+CtfImmTIMActivate(_In_ HKL hKL)
 {
     FIXME("(%p)\n", hKL);
     return E_NOTIMPL;
@@ -81,7 +345,8 @@ HRESULT WINAPI CtfImmTIMActivate(HKL hKL)
 /***********************************************************************
  *             CtfImmRestoreToolbarWnd(IMM32.@)
  */
-VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus)
+VOID WINAPI
+CtfImmRestoreToolbarWnd(_In_ DWORD dwStatus)
 {
     FIXME("(0x%lx)\n", dwStatus);
 }
@@ -89,7 +354,8 @@ VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus)
 /***********************************************************************
  *             CtfImmHideToolbarWnd(IMM32.@)
  */
-DWORD WINAPI CtfImmHideToolbarWnd(VOID)
+DWORD WINAPI
+CtfImmHideToolbarWnd(VOID)
 {
     FIXME("()\n");
     return 0;
@@ -98,7 +364,12 @@ DWORD WINAPI CtfImmHideToolbarWnd(VOID)
 /***********************************************************************
  *             CtfImmDispatchDefImeMessage(IMM32.@)
  */
-LRESULT WINAPI CtfImmDispatchDefImeMessage(HWND hWnd, UINT uMsg, WPARAM 
wParam, LPARAM lParam)
+LRESULT WINAPI
+CtfImmDispatchDefImeMessage(
+    _In_ HWND hWnd,
+    _In_ UINT uMsg,
+    _In_ WPARAM wParam,
+    _In_ LPARAM lParam)
 {
     /* FIXME("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam); */
     return 0;
@@ -107,7 +378,9 @@ LRESULT WINAPI CtfImmDispatchDefImeMessage(HWND hWnd, UINT 
uMsg, WPARAM wParam,
 /***********************************************************************
  *             CtfImmIsGuidMapEnable(IMM32.@)
  */
-BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC)
+BOOL WINAPI
+CtfImmIsGuidMapEnable(
+    _In_ HIMC hIMC)
 {
     DWORD dwThreadId;
     HKL hKL;
@@ -138,7 +411,11 @@ BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC)
 /***********************************************************************
  *             CtfImmGetGuidAtom(IMM32.@)
  */
-HRESULT WINAPI CtfImmGetGuidAtom(HIMC hIMC, DWORD dwUnknown, LPDWORD 
pdwGuidAtom)
+HRESULT WINAPI
+CtfImmGetGuidAtom(
+    _In_ HIMC hIMC,
+    _In_ DWORD dwUnknown,
+    _Out_ LPDWORD pdwGuidAtom)
 {
     HRESULT hr = E_FAIL;
     PIMEDPI pImeDpi;
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index 92ac837fffd..eec7202482a 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -1,3 +1,5 @@
+@ stdcall CtfAImmActivate(ptr)
+@ stdcall CtfAImmDeactivate(long)
 @ stdcall CtfImmIsCiceroEnabled()
 @ stdcall CtfImmIsTextFrameServiceDisabled()
 @ stdcall CtfImmTIMActivate(ptr)
diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h
index 6db1f8d6e4d..6e0512af409 100644
--- a/dll/win32/imm32/precomp.h
+++ b/dll/win32/imm32/precomp.h
@@ -143,7 +143,6 @@ BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC);
 #define IS_CROSS_THREAD_HIMC(hIMC)     
IS_TRUE_UNEXPECTEDLY(Imm32IsCrossThreadAccess(hIMC))
 #define IS_CROSS_PROCESS_HWND(hWnd)    
IS_TRUE_UNEXPECTEDLY(Imm32IsCrossProcessAccess(hWnd))
 #define ImeDpi_IsUnicode(pImeDpi)      ((pImeDpi)->ImeInfo.fdwProperty & 
IME_PROP_UNICODE)
-#define IS_16BIT_MODE()                (GetWin32ClientInfo()->dwTIFlags & 
TIF_16BIT)
 
 DWORD APIENTRY
 CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, 
DWORD dwBufLen,
@@ -189,3 +188,6 @@ PTHREADINFO FASTCALL Imm32CurrentPti(VOID);
 
 HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb);
 BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax);
+
+HRESULT CtfImmTIMCreateInputContext(_In_ HIMC hIMC);
+HRESULT CtfImmTIMDestroyInputContext(_In_ HIMC hIMC);
diff --git a/sdk/include/reactos/imm32_undoc.h 
b/sdk/include/reactos/imm32_undoc.h
index dadff68b031..49cb047182a 100644
--- a/sdk/include/reactos/imm32_undoc.h
+++ b/sdk/include/reactos/imm32_undoc.h
@@ -14,14 +14,16 @@ extern "C" {
 BOOL WINAPI
 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID 
pvSearchKey);
 
+BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx);
 PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc);
 VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc);
 PIMEDPI WINAPI ImmLockImeDpi(HKL hKL);
 VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi);
-HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC);
-HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC);
 HRESULT WINAPI CtfImmTIMActivate(HKL hKL);
 
+HRESULT WINAPI CtfAImmActivate(_Out_opt_ HINSTANCE *phinstCtfIme);
+HRESULT WINAPI CtfAImmDeactivate(_In_ BOOL bDestroy);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index e1a3ee9788a..1cb0fb2db4c 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -302,8 +302,9 @@ typedef struct _CALLBACKWND
 #define CI_INITTHREAD        0x00000008
 #define CI_CURTHPRHOOK       0x00000010
 #define CI_CLASSESREGISTERED 0x00000020
-#define CI_IMMACTIVATE       0x00000040
-#define CI_TFSDISABLED       0x00000400
+#define CI_IMMACTIVATE       0x00000040 /* IMM/IME (Asian input) */
+#define CI_TSFDISABLED       0x00000400 /* TSF (Text Services Framework a.k.a. 
Cicero) */
+#define CI_AIMMACTIVATED     0x00000800 /* Active IMM (AIMM) */
 
 /*
  * CLIENTINFO structure.
@@ -1231,6 +1232,7 @@ typedef enum IMEINFOEXCLASS
 #define IS_IME_HKL(hkl) ((((ULONG_PTR)(hkl)) & 0xF0000000) == 0xE0000000)
 #define IS_IMM_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32))
 #define IS_CICERO_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+#define IS_16BIT_MODE() (GetWin32ClientInfo()->dwTIFlags & TIF_16BIT)
 
 typedef struct tagIMEUI
 {

Reply via email to