Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

imemenu.c

Go to the documentation of this file.
00001 00002 // imemenu.c - IME Menu APIs 00003 // 00004 // handles IME specific menu retrieval 00005 // 00006 // Copyright (c) 1985 - 1999, Microsoft Corporation 00007 // 00008 // History: 00009 // 23-Mar-1997 hiroyama Created 00011 00012 #include "precomp.h" 00013 00014 #ifdef HIRO_DEBUG 00015 #define D(x) x 00016 #else 00017 #define D(x) 00018 #endif 00019 00020 #define IME_MENU_FILE_NAME L"ImmMenuInfo" 00021 #define IME_MENU_MAXMEM (128 * 1024) // maximum size of mapped file 00022 00024 // private structurs for inter process communication 00025 // 00026 // NOTE for NT50: these are dedicated to internat.exe 00027 // 00028 // uses memory mapped file as shared buffer 00029 // all strings expect UNICODE 00030 // HBITMAP is de-compiled and then compiled again using 00031 // internat.exe's context 00032 // 00034 00035 typedef struct _IMEMENU_BMP_HEADER { 00036 struct _IMEMENU_BMP_HEADER* lpNext; 00037 HBITMAP hBitmap; 00038 LPBYTE pBits; 00039 BITMAPINFO bmi; 00040 } IMEMENU_BMP_HEADER; 00041 00042 typedef struct { 00043 UINT cbSize; 00044 UINT fType; 00045 UINT fState; 00046 UINT wID; 00047 IMEMENU_BMP_HEADER* lpBmpChecked; 00048 IMEMENU_BMP_HEADER* lpBmpUnchecked; 00049 DWORD dwItemData; 00050 WCHAR szString[IMEMENUITEM_STRING_SIZE]; // menu string: always UNICODE. 00051 IMEMENU_BMP_HEADER* lpBmpItem; // NULL means no bitmap in this menu 00052 } IMEMENU_ITEM; 00053 00054 typedef struct { 00055 DWORD dwVersion; // holds version of this memory chunk 00056 DWORD dwMemSize; // size of memory buffer allocated 00057 DWORD dwFlags; // flags returned from IME 00058 DWORD dwType; 00059 IMEMENU_ITEM* lpImeParentMenu; // parent menu's offset (if any) passed from requester 00060 IMEMENU_ITEM* lpImeMenu; // offset to first menu item (will be set by IME side) 00061 DWORD dwSize; // number of menus to fill (not byte count) 00062 IMEMENU_BMP_HEADER* lpBmp; // offset to first bitmap header 00063 IMEMENU_BMP_HEADER* lpBmpNext; // points next available location for bmp buffer 00064 } IMEMENU_HEADER; 00065 00066 00067 // address conversion 00068 #define CONVTO_OFFSET(x) ((x) = (LPVOID)((x) ? ((LPBYTE)(x) - offset) : NULL)) 00069 #define CONVTO_PTR(x) ((x) = (LPVOID)((x) ? ((LPBYTE)(x) + offset) : NULL)) 00070 00071 #if DBG 00072 #define CHK_OFFSET(x) if ((ULONG_PTR)(x) >= pHeader->dwMemSize) { \ 00073 RIPMSG2(RIP_WARNING, "CHK_OFFSET(%s=%lx) is out of range.", #x, (ULONG_PTR)(x)); \ 00074 } 00075 #define CHK_PTR(x) if ((LPVOID)(x) < (LPVOID)pHeader || (LPBYTE)(x) > (LPBYTE)pHeader + pHeader->dwMemSize) { \ 00076 if ((x) != NULL) { \ 00077 RIPMSG2(RIP_WARNING, "CHK_PTR(%s=%lx) is out of range.", #x, (ULONG_PTR)(x)); \ 00078 DebugBreak(); \ 00079 } \ 00080 } 00081 #else 00082 #define CHK_OFFSET(x) 00083 #define CHK_PTR(x) if ((x) != NULL) { \ 00084 if ((LPVOID)(x) < (LPVOID)pHeader || (LPBYTE)(x) > (LPBYTE)pHeader + pHeader->dwMemSize) { \ 00085 goto cleanup; \ 00086 } \ 00087 } 00088 #endif 00089 00090 void ConvertImeMenuItemInfoAtoW(LPIMEMENUITEMINFOA lpA, LPIMEMENUITEMINFOW lpW, int nCP, BOOL copyBmp) 00091 { 00092 int i; 00093 00094 lpW->cbSize = lpA->cbSize; 00095 lpW->fType = lpA->fType; 00096 lpW->fState = lpA->fState; 00097 lpW->wID = lpA->wID; 00098 if (copyBmp) { 00099 lpW->hbmpChecked = lpA->hbmpChecked; 00100 lpW->hbmpUnchecked = lpA->hbmpUnchecked; 00101 lpW->hbmpItem = lpA->hbmpItem; 00102 } 00103 lpW->dwItemData = lpA->dwItemData; 00104 00105 i = MultiByteToWideChar(nCP, 00106 0, 00107 lpA->szString, 00108 lstrlenA(lpA->szString), 00109 lpW->szString, 00110 IMEMENUITEM_STRING_SIZE); 00111 00112 lpW->szString[i] = L'\0'; 00113 } 00114 00115 void ConvertImeMenuItemInfoWtoA(LPIMEMENUITEMINFOW lpW, LPIMEMENUITEMINFOA lpA, int nCP) 00116 { 00117 int i; 00118 BOOL bUDC; 00119 00120 lpA->cbSize = lpW->cbSize; 00121 lpA->fType = lpW->fType; 00122 lpA->fState = lpW->fState; 00123 lpA->wID = lpW->wID; 00124 lpA->hbmpChecked = lpW->hbmpChecked; 00125 lpA->hbmpUnchecked = lpW->hbmpUnchecked; 00126 lpA->dwItemData = lpW->dwItemData; 00127 lpA->hbmpItem = lpW->hbmpItem; 00128 00129 00130 i = WideCharToMultiByte(nCP, 00131 0, 00132 lpW->szString, 00133 wcslen(lpW->szString), 00134 lpA->szString, 00135 IMEMENUITEM_STRING_SIZE, 00136 (LPSTR)NULL, 00137 &bUDC); 00138 00139 lpA->szString[i] = '\0'; 00140 } 00141 00142 00143 #if DBG 00144 void DumpBytes(LPBYTE pb, UINT size) 00145 { 00146 UINT i; 00147 TRACE(("\npbmi dump:")); 00148 for (i = 0; i < size; ++i) { 00149 TRACE(("%02X ", pb[i] & 0xff)); 00150 } 00151 TRACE(("\n")); 00152 UNREFERENCED_PARAMETER(pb); // just in case 00153 } 00154 #else 00155 #define DumpBytes(a,b) 00156 #endif 00157 00159 // SaveBitmapToMemory 00160 00161 IMEMENU_BMP_HEADER* SaveBitmapToMemory(HDC hDC, HBITMAP hBmp, IMEMENU_BMP_HEADER* lpBH, IMEMENU_HEADER* pHeader) 00162 { 00163 HBITMAP hTmpBmp, hBmpOld; 00164 IMEMENU_BMP_HEADER* lpNext = NULL; 00165 PBITMAPINFO pbmi = &lpBH->bmi; 00166 ULONG sizBMI; 00167 00168 00169 if (!hBmp) { 00170 RIPMSG0(RIP_WARNING, "SaveBitmapToMemory: hBmp == NULL"); 00171 return NULL; 00172 } 00173 UserAssert(lpBH != NULL); 00174 00175 // 00176 // Let the graphics engine to retrieve the dimension of the bitmap for us 00177 // GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO 00178 // if BitCount != 0, color table will be retrieved 00179 // 00180 pbmi->bmiHeader.biSize = sizeof pbmi->bmiHeader; 00181 pbmi->bmiHeader.biBitCount = 0; // don't get the color table 00182 if ((GetDIBits(hDC, hBmp, 0, 0, (LPSTR)NULL, pbmi, DIB_RGB_COLORS)) == 0) { 00183 RIPMSG0(RIP_WARNING, "SaveBitmapToMemory: failed to GetDIBits(NULL)"); 00184 return NULL; 00185 } 00186 00187 00188 // 00189 // Note: 24 bits per pixel has no color table. So, we don't have to 00190 // allocate memory for retrieving that. Otherwise, we do. 00191 // 00192 switch (pbmi->bmiHeader.biBitCount) { 00193 case 24: // has color table 00194 sizBMI = sizeof(BITMAPINFOHEADER); 00195 break; 00196 case 16: 00197 case 32: 00198 sizBMI = sizeof(BITMAPINFOHEADER) + sizeof(DWORD) * 3; 00199 break; 00200 default: 00201 sizBMI = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << pbmi->bmiHeader.biBitCount); 00202 break; 00203 00204 } 00205 00206 // 00207 // check if the buffer has enough space to put bitmap 00208 // 00209 if ((LPBYTE)pHeader + pHeader->dwMemSize < (LPBYTE)lpBH + sizeof lpBH + sizBMI + pbmi->bmiHeader.biSizeImage) { 00210 RIPMSG0(RIP_WARNING, "SaveBitmapToMemory: size of bmp image(s) exceed limit "); 00211 return FALSE; 00212 } 00213 00214 // 00215 // Now that we know the size of the image, let pBits point the given buffer 00216 // 00217 lpBH->pBits = (LPBYTE)pbmi + sizBMI; 00218 00219 // 00220 // Bitmap can't be selected into a DC when calling GetDIBits 00221 // Assume that the hDC is the DC where the bitmap would have been selected 00222 // if indeed it has been selected 00223 // 00224 if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight)) { 00225 hBmpOld = SelectObject(hDC, hTmpBmp); 00226 if (GetDIBits(hDC, hBmp, 0, pbmi->bmiHeader.biHeight, (LPSTR)lpBH->pBits, pbmi, DIB_RGB_COLORS) == 0){ 00227 SelectObject(hDC, hBmpOld); 00228 RIPMSG0(RIP_WARNING, "SaveBitmapToMemory: GetDIBits() failed."); 00229 return NULL; 00230 } 00231 lpNext = (IMEMENU_BMP_HEADER*)((LPBYTE)pbmi + sizBMI + pbmi->bmiHeader.biSizeImage); 00232 00233 DumpBytes((LPBYTE)pbmi, sizeof *pbmi); 00234 } else { 00235 RIPMSG0(RIP_WARNING, "SaveBitmapToMemory: CreateCompatibleBitmap() failed."); 00236 return NULL; 00237 } 00238 00239 SelectObject(hDC, hBmpOld); 00240 DeleteObject(hTmpBmp); 00241 return lpNext; 00242 } 00243 00245 // DecompileBitmap() 00246 // 00247 // decompile given hBitmap into IMEMENU_BMP_HEADER 00248 // manupilate IMEMENU_BMP_HEADER links in IMEMENU_HEADER 00249 // 00250 // History: 00251 // 23-Mar-1997 HiroYama Created 00253 00254 IMEMENU_BMP_HEADER* DecompileBitmap(IMEMENU_HEADER* pHeader, HBITMAP hBitmap) 00255 { 00256 IMEMENU_BMP_HEADER* pBmp = pHeader->lpBmp; 00257 HDC hDC; 00258 00259 // first search handled bitmap 00260 while (pBmp) { 00261 if (pBmp->hBitmap == hBitmap) { 00262 // if hBitmap is already de-compiled, return it 00263 return pBmp; 00264 } 00265 pBmp = pBmp->lpNext; 00266 } 00267 00268 // not yet allocated, so prepare memory buffer 00269 pBmp = pHeader->lpBmpNext; 00270 UserAssert(pBmp != NULL); 00271 CHK_PTR(pBmp); 00272 if (pBmp == NULL) { 00273 RIPMSG1(RIP_WARNING, "DecompileBitmap: pBmp == NULL in L%d", __LINE__); 00274 return NULL; 00275 } 00276 00277 // use desktop's DC 00278 hDC = GetDC(GetDesktopWindow()); 00279 if (hDC == NULL) { 00280 RIPMSG1(RIP_WARNING, "DecompileBitmap: hDC == NULL in L%d", __LINE__); 00281 return NULL; 00282 } 00283 00284 // 00285 // decompile hBitmap 00286 // 00287 pBmp->lpNext = pHeader->lpBmp; 00288 pHeader->lpBmpNext = SaveBitmapToMemory(hDC, hBitmap, pBmp, pHeader); 00289 if (pHeader->lpBmpNext == NULL) { 00290 RIPMSG1(RIP_WARNING, "DecompileBitmap: pHeader->lpBmpNext == NULL in L%d", __LINE__); 00291 // error case. restore bmp link, then returns NULL 00292 pHeader->lpBmpNext = pBmp; 00293 pHeader->lpBmp = pBmp->lpNext; 00294 pBmp = NULL; 00295 goto cleanup; 00296 } 00297 00298 // if succeeded, mark this BITMAP_HEADER with hBitmap 00299 pBmp->hBitmap = hBitmap; 00300 00301 // 00302 // put this BITMAP_HEADER in linked list 00303 // 00304 pHeader->lpBmp = pBmp; 00305 00306 cleanup: 00307 if (hDC) 00308 ReleaseDC(GetDesktopWindow(), hDC); 00309 return pBmp; 00310 } 00311 00313 // ImmPutImeMenuItemsIntoMappedFile() 00314 // 00315 // Interprocess IME Menu handler 00316 // 00317 // called from ImeSystemHandler() in user32.dll 00318 // 00319 // handler of WM_IME_SYSTEM:IMS_MENU_ITEM 00320 // 00321 // History: 00322 // 23-Mar-1997 HiroYama Created 00324 00325 LRESULT ImmPutImeMenuItemsIntoMappedFile(HIMC hImc) 00326 { 00327 HANDLE hMap = NULL; 00328 LPVOID lpMap = NULL; 00329 IMEMENU_HEADER* pHeader; 00330 LPIMEMENUITEMINFO lpBuf = NULL; 00331 IMEMENU_ITEM* pMenu; 00332 IMEMENU_BMP_HEADER* pBmp; 00333 LRESULT lRet = 0; 00334 ULONG_PTR offset; 00335 DWORD i; 00336 00337 // Open memory mapped file 00338 hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, IME_MENU_FILE_NAME); 00339 if (hMap == NULL) { 00340 RIPMSG0(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: cannot open mapped file."); 00341 return 0L; 00342 } 00343 00344 // Map entire view of the file into the process memory space 00345 lpMap = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); 00346 if (lpMap == NULL) { 00347 RIPMSG0(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: cannot map view of file."); 00348 goto cleanup; 00349 // I wish if I could use C++... 00350 } 00351 00352 pHeader = (IMEMENU_HEADER*)lpMap; 00353 00355 // Version check 00357 if (pHeader->dwVersion != 1) { 00358 RIPMSG1(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: dwVersion(%d) does not match.", 00359 pHeader->dwVersion); 00360 goto cleanup; 00361 } 00362 00364 // convert offset to pointer 00365 offset = (ULONG_PTR)pHeader; 00366 CONVTO_PTR(pHeader->lpImeParentMenu); 00367 CHK_PTR(pHeader->lpImeParentMenu); 00368 pMenu = CONVTO_PTR(pHeader->lpImeMenu); 00369 CHK_PTR(pHeader->lpImeMenu); 00370 if (pHeader->dwSize) { 00371 UserAssert(pHeader->lpImeMenu); // if dwSize is specified, we need real buffer here 00372 lpBuf = ImmLocalAlloc(HEAP_ZERO_MEMORY, pHeader->dwSize * sizeof(IMEMENUITEMINFOW)); 00373 if (lpBuf == NULL) { 00374 RIPMSG0(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: not enough memory for receiver's buffer."); 00375 goto cleanup; 00376 } 00377 } 00378 00379 00380 // preparation 00381 #if DBG 00382 if (pHeader->lpImeParentMenu) { 00383 UserAssert(!pHeader->lpImeParentMenu->lpBmpChecked && 00384 !pHeader->lpImeParentMenu->lpBmpUnchecked && 00385 !pHeader->lpImeParentMenu->lpBmpItem); 00386 } 00387 #endif 00388 00390 // Get IME menus 00391 pHeader->dwSize = ImmGetImeMenuItemsW(hImc, pHeader->dwFlags, pHeader->dwType, 00392 (LPIMEMENUITEMINFOW)pHeader->lpImeParentMenu, lpBuf, 00393 pHeader->dwSize * sizeof(IMEMENUITEMINFOW)); 00394 // now, pHeader->dwSize contains number of menu items rather than byte size 00395 if (pHeader->dwSize == 0) { 00396 goto cleanup; 00397 } 00399 00400 // 00401 // Copy back the information 00402 // 00403 // if lpBuf != NULL, we need to copy back information 00404 // 00405 if (lpBuf) { 00406 LPIMEMENUITEMINFO lpMenuW = lpBuf; 00407 00408 pHeader->lpBmp = NULL; 00409 // lpBmpNext will point first possible memory for bmp de-compile 00410 pHeader->lpBmpNext = (LPVOID)((LPBYTE)pHeader + (pHeader->dwSize + 1) * sizeof(IMEMENUITEMINFOW)); 00411 00412 // copy menuinfo 00413 for (i = 0; i < pHeader->dwSize; ++i, ++pMenu, ++lpMenuW) { 00414 RtlCopyMemory(pMenu, lpMenuW, sizeof *lpMenuW); 00415 // decompile hbitmap 00416 if (lpMenuW->hbmpChecked) { 00417 if ((pMenu->lpBmpChecked = DecompileBitmap(pHeader, lpMenuW->hbmpChecked)) == NULL) { 00418 RIPMSG1(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: DecompileBitmap Failed in L%d", __LINE__); 00419 goto cleanup; 00420 } 00421 } 00422 if (lpMenuW->hbmpUnchecked) { 00423 if ((pMenu->lpBmpUnchecked = DecompileBitmap(pHeader, lpMenuW->hbmpUnchecked)) == NULL) { 00424 RIPMSG1(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: DecompileBitmap Failed in L%d", __LINE__); 00425 goto cleanup; 00426 } 00427 } 00428 if (lpMenuW->hbmpItem) { 00429 if ((pMenu->lpBmpItem = DecompileBitmap(pHeader, lpMenuW->hbmpItem)) == NULL) { 00430 RIPMSG1(RIP_WARNING, "ImmPutImeMenuItemsIntoMappedFile: DecompileBitmap Failed in L%d", __LINE__); 00431 goto cleanup; 00432 } 00433 } 00434 } 00435 00437 // 00438 // convert pointer to offset 00439 // 00440 00441 pMenu = pHeader->lpImeMenu; 00442 CONVTO_OFFSET(pHeader->lpImeMenu); 00443 // no need to convert parent menu, so let it be NULL 00444 D(pHeader->lpImeParentMenu = NULL); 00445 00446 // pointer to BITMAP_HEADER in each menu 00447 for (i = 0; i < pHeader->dwSize; ++i, ++pMenu) { 00448 TRACE(("ImmPutImeMenuItemsIntoMappedFile: convertiong '%S'\n", pMenu->szString)); 00449 CONVTO_OFFSET(pMenu->lpBmpChecked); 00450 CONVTO_OFFSET(pMenu->lpBmpUnchecked); 00451 TRACE(("ImmPutImeMenuItemsIntoMappedFile: before conversion (%#lx)\n", pMenu->lpBmpItem)); 00452 CONVTO_OFFSET(pMenu->lpBmpItem); 00453 TRACE(("ImmPutImeMenuItemsIntoMappedFile: after conversion (%#lx)\n", pMenu->lpBmpItem)); 00454 00455 // check them 00456 CHK_OFFSET(pMenu->lpBmpChecked); 00457 CHK_OFFSET(pMenu->lpBmpChecked); 00458 CHK_OFFSET(pMenu->lpBmpItem); 00459 } 00460 00461 // 00462 // first pointer to BITMAP_HEADER linked list 00463 // 00464 pBmp = pHeader->lpBmp; 00465 CONVTO_OFFSET(pHeader->lpBmp); 00466 CHK_OFFSET(pHeader->lpBmp); 00467 // pHeader->lpBmpNext will not be used, so let it be NULL 00468 D(pHeader->lpBmpNext = NULL); 00469 00470 // 00471 // pointers in BITMAP_HEADER linked list 00472 // 00473 while (pBmp) { 00474 IMEMENU_BMP_HEADER* ptBmp = pBmp->lpNext; 00475 CONVTO_OFFSET(pBmp->pBits); 00476 CONVTO_OFFSET(pBmp->lpNext); 00477 CHK_OFFSET(pBmp->lpNext); 00478 pBmp = ptBmp; 00479 } 00480 // 00481 // pointer conversion finished 00482 // 00484 } // end if (lpBuf) 00485 00486 // 00487 // everything went OK 00488 // 00489 lRet = 1; 00490 00491 cleanup: 00492 if (lpBuf) 00493 ImmLocalFree(lpBuf); 00494 if (lpMap) 00495 UnmapViewOfFile(lpMap); 00496 if (hMap) 00497 CloseHandle(hMap); 00498 return lRet; 00499 } 00500 00501 00503 // InternalImeMenuCreateBitmap() 00504 // 00505 // create bitmap from IMEMENU_BMP_HEADER 00507 00508 HBITMAP InternalImeMenuCreateBitmap(IMEMENU_BMP_HEADER* lpBH) 00509 { 00510 HDC hDC; 00511 00512 if (lpBH == NULL) { 00513 RIPMSG1(RIP_WARNING, "InternalImeMenuCreateBitmap: lpBH == NULL in L%d", __LINE__); 00514 return NULL; 00515 } 00516 if (lpBH->pBits == NULL) { 00517 RIPMSG1(RIP_WARNING, "InternalImeMenuCreateBitmap: lpBH->pBits == NULL in L%d", __LINE__); 00518 return NULL; 00519 } 00520 00521 if (lpBH->hBitmap) { 00522 TRACE(("InternalImeMenuCreateBitmap: lpBH->hBitmap != NULL. will return it.\n")); 00523 return lpBH->hBitmap; 00524 } 00525 00526 if (hDC = GetDC(GetDesktopWindow())) { 00527 HDC hMyDC = CreateCompatibleDC(hDC); 00528 if (hMyDC) { 00529 // (select palette) needed ? 00530 lpBH->hBitmap = CreateDIBitmap(hDC, &lpBH->bmi.bmiHeader, CBM_INIT, 00531 lpBH->pBits, &lpBH->bmi, DIB_RGB_COLORS); 00532 if (lpBH->hBitmap == NULL) { 00533 DWORD dwErr = GetLastError(); 00534 RIPMSG1(RIP_WARNING, "InternalImeMenuCreateBitmap: CreateDIBitmap Failed. Last error=%#x\n", dwErr); 00535 } 00536 DeleteDC(hMyDC); 00537 } 00538 else { 00539 RIPMSG0(RIP_WARNING, "InternalImeMenuCreateBitmap: CreateCompatibleDC failed."); 00540 } 00541 00542 ReleaseDC(GetDesktopWindow(), hDC); 00543 } 00544 else { 00545 RIPMSG0(RIP_WARNING, "InternalImeMenuCreateBitmap: couldn't get Desktop DC."); 00546 } 00547 return lpBH->hBitmap; 00548 } 00549 00551 // ImmGetImeMenuItemsInterProcess() 00552 // 00553 // Inter process IME Menu handler 00554 // sends WM_IME_SYSTEM:IMS_GETIMEMENU 00555 // 00556 // History: 00557 // 23-Mar-1997 HiroYama Created 00559 00560 DWORD ImmGetImeMenuItemsInterProcess(HIMC hImc, 00561 DWORD dwFlags, 00562 DWORD dwType, 00563 LPIMEMENUITEMINFOW lpParentMenu, 00564 LPIMEMENUITEMINFOW lpMenu, 00565 DWORD dwSize) 00566 { 00567 HWND hwnd; 00568 HANDLE hMemFile = NULL; 00569 DWORD dwRet = 0; 00570 LPBYTE lpMap = NULL; 00571 IMEMENU_HEADER* pHeader; 00572 IMEMENU_ITEM* pMenuItem; 00573 IMEMENU_BMP_HEADER* pBmpHeader; 00574 DWORD i; 00575 ULONG_PTR offset; 00576 00577 // Get default IME window 00578 // 00579 // Note: We do not consider user created HIMC here, because this inter-process call is intended to 00580 // support only internat.exe, and this message is passed as just a kick to IMM's def WinProc. 00581 hwnd = (HWND)NtUserQueryInputContext(hImc, InputContextDefaultImeWindow); 00582 if (hwnd == NULL || !IsWindow(hwnd)) { 00583 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemsInterProcess: hwnd(%lx) is not a valid window.", hwnd); 00584 return 0; 00585 } 00586 00587 RtlEnterCriticalSection(&gcsImeDpi); 00588 00589 // first, create memory mapped file 00590 hMemFile = CreateFileMapping((HANDLE)~0, NULL, PAGE_READWRITE, 00591 0, IME_MENU_MAXMEM, IME_MENU_FILE_NAME); 00592 if (hMemFile == NULL) { 00593 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsInterProcess: cannot allocate memory mapped file."); 00594 goto cleanup; 00595 } 00596 // then get a view of the mapped file 00597 lpMap = (LPBYTE)MapViewOfFile(hMemFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 00598 if (lpMap == NULL) { 00599 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsInterProcess: cannot map view of memory mapped file."); 00600 goto cleanup; 00601 } 00602 00603 // 00604 // shared buffer (memory mapped file) initialization 00605 // 00606 pHeader = (IMEMENU_HEADER*)lpMap; 00607 RtlZeroMemory(pHeader, sizeof *pHeader); 00608 pHeader->dwVersion = 1; 00609 pHeader->dwMemSize = IME_MENU_MAXMEM; 00610 pHeader->dwSize = dwSize / sizeof(IMEMENUITEMINFOW); // CAUTION: dwSize could be 0. 00611 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemsInterProcess: pHeader->dwSize=%ld", pHeader->dwSize); 00612 pHeader->dwFlags = dwFlags; 00613 pHeader->dwType = dwType; 00614 00615 // 00616 // 1) dwSize != 0 and lpMenu != NULL means, caller requests the given buffer filled 00617 // 2) if lpParentMenu is passed, we need to put its information in shared buffer 00618 // 00619 if ((dwSize && lpMenu) || lpParentMenu) { 00620 // if parent menu is specified, copy it here 00621 if (lpParentMenu) { 00622 IMEMENU_ITEM* pPMenu = 00623 pHeader->lpImeParentMenu = (IMEMENU_ITEM*)&pHeader[1]; 00624 00625 RtlCopyMemory(pPMenu, lpParentMenu, sizeof(IMEMENUITEMINFOW)); 00626 00627 // by design, IME will receive NULL hbmpItem in parent menu. 00628 // there is no way to guarantee the same hbmpItem is returned, thus NULL is passed. 00629 pPMenu->lpBmpChecked = pPMenu->lpBmpUnchecked = pPMenu->lpBmpItem = NULL; 00630 pHeader->lpImeMenu = pHeader->lpImeParentMenu + 1; 00631 } 00632 else { 00633 pHeader->lpImeParentMenu = NULL; 00634 pHeader->lpImeMenu = (LPVOID)&pHeader[1]; 00635 } 00636 // convert pointer to offset 00637 offset = (ULONG_PTR)lpMap; 00638 CONVTO_OFFSET(pHeader->lpImeParentMenu); 00639 CONVTO_OFFSET(pHeader->lpImeMenu); 00640 } 00641 00642 00643 00644 00646 if (!SendMessage(hwnd, WM_IME_SYSTEM, IMS_GETIMEMENU, (LPARAM)hImc)) { 00647 // if it fails 00648 goto cleanup; 00649 } 00651 00652 // NOTE: dwSize is maximum index of menu array. not a total byte size of array. 00653 dwSize = pHeader->dwSize; 00654 00655 if (lpMenu) { 00657 // convert offset to pointer 00659 pMenuItem = CONVTO_PTR(pHeader->lpImeMenu); 00660 CHK_PTR(pMenuItem); 00661 // NOTE: we don't have to handle parent menu 00662 00663 // 00664 // pointers to BITMAP_HEADER in each menu structure 00665 // 00666 for (i = 0; i < dwSize; ++i, ++pMenuItem) { 00667 CONVTO_PTR(pMenuItem->lpBmpChecked); 00668 CONVTO_PTR(pMenuItem->lpBmpUnchecked); 00669 CONVTO_PTR(pMenuItem->lpBmpItem); 00670 // 00671 // check the pointers 00672 // 00673 CHK_PTR(pMenuItem->lpBmpChecked); 00674 CHK_PTR(pMenuItem->lpBmpUnchecked); 00675 CHK_PTR(pMenuItem->lpBmpItem); 00676 } 00677 00678 // 00679 // pointer to first BITMAP_HEADER 00680 // 00681 pBmpHeader = CONVTO_PTR(pHeader->lpBmp); 00682 00683 // 00684 // each BITMAP_HEADER 00685 // 00686 while (pBmpHeader) { 00687 pBmpHeader->hBitmap = NULL; // clear 00688 // pBits 00689 CONVTO_PTR(pBmpHeader->pBits); 00690 CHK_PTR(pBmpHeader->pBits); 00691 00692 // next BITMAP_HEADER 00693 pBmpHeader = CONVTO_PTR(pBmpHeader->lpNext); 00694 CHK_PTR(pBmpHeader); 00695 } 00696 00697 // 00698 // copy back the results 00699 // 00700 pMenuItem = pHeader->lpImeMenu; 00701 for (i = 0; i < dwSize; ++i, ++pMenuItem, ++lpMenu) { 00702 lpMenu->cbSize = pMenuItem->cbSize; 00703 lpMenu->fType = pMenuItem->fType; 00704 lpMenu->fState = pMenuItem->fState; 00705 lpMenu->wID = pMenuItem->wID; 00706 lpMenu->dwItemData = pMenuItem->dwItemData; 00707 wcscpy(lpMenu->szString, pMenuItem->szString); 00708 00709 // Create bitmap from memory buffer 00710 // hbmp will be NULL if no bmp is specified. 00711 if (pMenuItem->lpBmpChecked) { 00712 lpMenu->hbmpChecked = InternalImeMenuCreateBitmap(pMenuItem->lpBmpChecked); 00713 } 00714 else { 00715 lpMenu->hbmpChecked = NULL; 00716 } 00717 if (pMenuItem->lpBmpUnchecked) { 00718 lpMenu->hbmpUnchecked = InternalImeMenuCreateBitmap(pMenuItem->lpBmpUnchecked); 00719 } 00720 else { 00721 lpMenu->hbmpUnchecked = NULL; 00722 } 00723 if (pMenuItem->lpBmpItem) { 00724 lpMenu->hbmpItem = InternalImeMenuCreateBitmap(pMenuItem->lpBmpItem); 00725 } 00726 else { 00727 lpMenu->hbmpItem = NULL; 00728 } 00729 } 00730 } 00731 00732 00733 cleanup: 00734 if (lpMap) { 00735 UnmapViewOfFile(lpMap); 00736 } 00737 RtlLeaveCriticalSection(&gcsImeDpi); 00738 // destroy memory mapped file 00739 if (hMemFile) { 00740 CloseHandle(hMemFile); 00741 } 00742 00743 return dwSize; 00744 } 00745 00747 // ImmGetImeMenuItemsWorker() 00748 // 00749 // Handler of IME Menu 00750 // 00751 // if specified HIMC belongs to other process, it calls 00752 // ImmGetImeMenuItemsInterProcess() 00753 // 00754 // History: 00755 // 23-Mar-1997 HiroYama Created 00757 00758 00759 DWORD ImmGetImeMenuItemsWorker(HIMC hIMC, 00760 DWORD dwFlags, 00761 DWORD dwType, 00762 LPVOID lpImeParentMenu, 00763 LPVOID lpImeMenu, 00764 DWORD dwSize, 00765 BOOL bAnsiOrigin) 00766 { 00767 BOOL bAnsiIme = IsAnsiIMC(hIMC); 00768 DWORD dwRet = 0; 00769 LPINPUTCONTEXT lpInputContext; 00770 DWORD dwThreadId; 00771 PIMEDPI pImeDpi = NULL; 00772 LPVOID lpImePTemp = lpImeParentMenu; // keeps parent menu 00773 LPVOID lpImeTemp = lpImeMenu; // points menu buffer 00774 IMEMENUITEMINFOA imiiParentA; 00775 IMEMENUITEMINFOW imiiParentW; 00776 00777 // 00778 // check if the call will be inter process 00779 // 00780 { 00781 DWORD dwProcessId = GetInputContextProcess(hIMC); 00782 if (dwProcessId == 0) { 00783 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsWorker: dwProcessId == 0"); 00784 return 0; 00785 } 00786 if (dwProcessId != GetCurrentProcessId()) { 00787 // 00788 // going to call another process' IME 00789 // 00790 TRACE(("ImmGetImeMenuItemsWorker: Inter process.\n")); 00791 if (bAnsiOrigin) { 00792 // 00793 // this inter-process thing is only allowed to internat.exe or equivalent 00794 // 00795 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsWorker: interprocess getmenu is not allowed for ANSI caller."); 00796 return 0; 00797 } 00798 return ImmGetImeMenuItemsInterProcess(hIMC, dwFlags, dwType, lpImeParentMenu, 00799 lpImeMenu, dwSize); 00800 } 00801 } 00802 00803 // 00804 // within process 00805 // 00806 00807 if (hIMC == NULL || (lpInputContext = ImmLockIMC(hIMC)) == NULL) { 00808 RIPMSG2(RIP_WARNING, "ImmGetImeMenuItemsWorker: illegal hIMC(%#lx) in L%d", hIMC, __LINE__); 00809 return 0; 00810 } 00811 00812 dwThreadId = GetInputContextThread(hIMC); 00813 if (dwThreadId == 0) { 00814 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemsWorker: dwThreadId = 0 in L%d", __LINE__); 00815 goto cleanup; 00816 } 00817 if ((pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId))) == NULL) { 00818 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemWorker: pImeDpi == NULL in L%d.", __LINE__); 00819 goto cleanup; 00820 } 00821 00822 #if 0 // NT: we don't keep version info in ImeDpi 00823 if (pImeDpi->dwWinVersion <= IMEVER_0310) { 00824 RIPMSG1(RIP_WARNING, "GetImeMenuItems: OldIME does not support this. %lx", hIMC); 00825 goto cleanup; 00826 } 00827 #endif 00828 00829 // 00830 // if IME does not support IME Menu, do nothing 00831 // 00832 if (pImeDpi->pfn.ImeGetImeMenuItems) { 00833 LPVOID lpNewBuf = NULL; 00834 00835 TRACE(("ImmGetImeMenuItemsWorker: IME has menu callback.\n")); 00836 00837 if (bAnsiIme != bAnsiOrigin) { 00838 // 00839 // we need A/W translation before calling IME 00840 // 00841 if (bAnsiOrigin) { 00842 // ANSI API and UNICODE IME. 00843 // A to W conversion needed here 00844 if (lpImeParentMenu) { 00845 // parent menu is specified. need conversion 00846 lpImePTemp = (LPVOID)&imiiParentW; 00847 ConvertImeMenuItemInfoAtoW((LPIMEMENUITEMINFOA)lpImeParentMenu, 00848 (LPIMEMENUITEMINFOW)lpImePTemp, 00849 CP_ACP, TRUE); // ANSI app, UNICODE IME: let's use CP_ACP 00850 } 00851 if (lpImeMenu) { 00852 // allocate memory block for temporary storage 00853 DWORD dwNumBuffer = dwSize / sizeof(IMEMENUITEMINFOA); 00854 dwSize = dwNumBuffer * sizeof(IMEMENUITEMINFOW); 00855 if (dwSize == 0) { 00856 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsWorker: (AtoW) dwSize is 0."); 00857 goto cleanup; 00858 } 00859 lpImeTemp = lpNewBuf = ImmLocalAlloc(0, dwSize); 00860 TRACE(("ImmGetImeMenuItemsWorker: for UNICODE IME memory allocated %d bytes. lpNewBuf=%#x\n", dwSize, lpNewBuf)); 00861 if (lpNewBuf == NULL) { 00862 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemsWorker: cannot alloc lpNewBuf in L%d", __LINE__); 00863 goto cleanup; 00864 } 00865 } 00866 } 00867 else { 00868 // UNICODE API and ANSI IME. 00869 // W to A conversion needed here 00870 if (lpImeParentMenu) { 00871 // parent menu is speicified. need conversion 00872 lpImePTemp = (LPVOID)&imiiParentA; 00873 ConvertImeMenuItemInfoWtoA((LPIMEMENUITEMINFOW)lpImeParentMenu, 00874 (LPIMEMENUITEMINFOA)lpImePTemp, 00875 pImeDpi->dwCodePage); // Note: hopefully in the future, this can be changed to IMECodePage(pImeDpi) 00876 } 00877 if (lpImeMenu) { 00878 // allocate memory block for temporary storage 00879 DWORD dwNumBuffer = dwSize / sizeof(IMEMENUITEMINFOW); 00880 dwSize = dwNumBuffer / sizeof(IMEMENUITEMINFOA); 00881 if (dwSize == 0) { 00882 RIPMSG0(RIP_WARNING, "ImmGetImeMenuItemsWorker: (WtoA) dwSize is 0."); 00883 goto cleanup; 00884 } 00885 lpImeTemp = lpNewBuf = ImmLocalAlloc(0, dwSize); 00886 RIPMSG2(RIP_WARNING, "ImmGetImeMenuItemsWorker: for ANSI IME memory allocated %d bytes. lpNewBuf=%#x", dwSize, lpNewBuf); 00887 if (lpNewBuf == NULL) { 00888 RIPMSG1(RIP_WARNING, "ImmGetImeMenuItemsWorker: cannot alloc lpNewBuf in L%d", __LINE__); 00889 goto cleanup; 00890 } 00891 } 00892 } 00893 } 00894 00896 dwRet = pImeDpi->pfn.ImeGetImeMenuItems(hIMC, dwFlags, dwType, lpImePTemp, lpImeTemp, dwSize); 00898 00899 // 00900 // back-conversion needed if: 00901 // 1) IME returns menus, and 00902 // 2) A/W is different between caller and IME, and 00903 // 3) caller wants the buffer to be filled 00904 // 00905 if (dwRet && bAnsiIme != bAnsiOrigin && lpImeTemp) { 00906 if (bAnsiOrigin) { 00907 // ANSI API and UNICODE IME. 00908 // W to A conversion needed here 00909 LPIMEMENUITEMINFOW lpW = (LPIMEMENUITEMINFOW)lpImeTemp; 00910 LPIMEMENUITEMINFOA lpA = (LPIMEMENUITEMINFOA)lpImeMenu; 00911 DWORD i; 00912 00913 for (i = 0; i < dwRet; ++i) { 00914 ConvertImeMenuItemInfoWtoA((LPIMEMENUITEMINFOW)lpW++, 00915 (LPIMEMENUITEMINFOA)lpA++, 00916 CP_ACP); // ANSI app and UNICODE IME: let's use CP_ACP 00917 } 00918 } 00919 else { 00920 // UNICODE API and ANSI IME. 00921 // A to W conversion needed here 00922 LPIMEMENUITEMINFOA lpA = (LPIMEMENUITEMINFOA)lpImeTemp; 00923 LPIMEMENUITEMINFOW lpW = (LPIMEMENUITEMINFOW)lpImeMenu; 00924 DWORD i; 00925 00926 for (i = 0; i < dwSize; i++) { 00927 ConvertImeMenuItemInfoAtoW((LPIMEMENUITEMINFOA)lpA++, 00928 (LPIMEMENUITEMINFOW)lpW++, 00929 pImeDpi->dwCodePage, // Note: hopefully in the future, this can be changed to IMECodePage(pImeDpi) 00930 TRUE); // copy hbitmap also 00931 } 00932 } 00933 } 00934 00935 // free temporary buffer if we've allocated it 00936 if (lpNewBuf) 00937 ImmLocalFree(lpNewBuf); 00938 } // end if IME has menu callback 00939 00940 cleanup: 00941 if (pImeDpi) { 00942 ImmUnlockImeDpi(pImeDpi); 00943 } 00944 00945 if (hIMC != NULL) { 00946 ImmUnlockIMC(hIMC); 00947 } 00948 00949 return dwRet; 00950 } 00951 00952 00953 DWORD WINAPI ImmGetImeMenuItemsA( 00954 HIMC hIMC, 00955 DWORD dwFlags, 00956 DWORD dwType, 00957 LPIMEMENUITEMINFOA lpImeParentMenu, 00958 LPIMEMENUITEMINFOA lpImeMenu, 00959 DWORD dwSize) 00960 { 00961 return ImmGetImeMenuItemsWorker(hIMC, dwFlags, dwType, 00962 (LPVOID)lpImeParentMenu, 00963 (LPVOID)lpImeMenu, dwSize, TRUE /* ANSI origin */); 00964 } 00965 00966 00967 DWORD WINAPI ImmGetImeMenuItemsW( 00968 HIMC hIMC, 00969 DWORD dwFlags, 00970 DWORD dwType, 00971 LPIMEMENUITEMINFOW lpImeParentMenu, 00972 LPIMEMENUITEMINFOW lpImeMenu, 00973 DWORD dwSize) 00974 { 00975 return ImmGetImeMenuItemsWorker(hIMC, dwFlags, dwType, 00976 (LPVOID)lpImeParentMenu, 00977 (LPVOID)lpImeMenu, dwSize, FALSE /* UNICODE origin */); 00978 }

Generated on Sat May 15 19:40:21 2004 for test by doxygen 1.3.7