ReactOS 0.4.16-dev-2491-g3dc6630
imemenu.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IME menus
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020-2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10 */
11
12#include "precomp.h"
13
15
16// See also: https://github.com/katahiromz/ImeMenuTest3
17
18#define IMEMENUINFO_BUFFER_SIZE 0x20000
19#define IMEMENUINFO_MAPPING_NAME L"ImmMenuInfo"
20
21// IME menu info. 95% or more compatible to Windows
22typedef struct tagIMEMENUINFO
23{
24 DWORD dwVersion; // Must be 1
25 DWORD dwBufferSize; // Always 0x20000 (128KB)
26 DWORD dwFlags; // dwFlags of ImmGetImeMenuItems
27 DWORD dwType; // dwType of ImmGetImeMenuItems
28 ULONG_PTR dwParentOffset; // Relative offset to parent menu data (or pointer)
29 ULONG_PTR dwItemsOffset; // Relative offset to menu items (or pointer)
30 DWORD dwCount; // # of items
31 ULONG_PTR dwBitmapListOffset; // Relative offset to bitmap-node list head (or pointer)
32 ULONG_PTR dwEndOffset; // Offset to the bottom of this data (or pointer)
34
35typedef struct tagBITMAPNODE
36{
37 ULONG_PTR dwNext; // Relative offset to next node (or pointer)
38 HBITMAP hbmpCached; // Cached HBITMAP
39 ULONG_PTR dibBitsPtr; // Relative offset to DIB pixel data (or pointer)
40 BITMAPINFOHEADER bmih; // BITMAPINFOHEADER
42
43#define PTR_FROM_OFFSET(head, offset) (PVOID)((PBYTE)(head) + (SIZE_T)(offset))
44
45/* Convert ANSI IME menu to Wide */
46static BOOL
48 _In_ const IMEMENUITEMINFOA *pItemA,
49 _Out_ PIMEMENUITEMINFOW pItemW,
50 _In_ UINT uCodePage,
51 _In_ BOOL bBitmap)
52{
53 INT ret;
54 pItemW->cbSize = pItemA->cbSize;
55 pItemW->fType = pItemA->fType;
56 pItemW->fState = pItemA->fState;
57 pItemW->wID = pItemA->wID;
58 if (bBitmap)
59 {
60 pItemW->hbmpChecked = pItemA->hbmpChecked;
61 pItemW->hbmpUnchecked = pItemA->hbmpUnchecked;
62 pItemW->hbmpItem = pItemA->hbmpItem;
63 }
64 pItemW->dwItemData = pItemA->dwItemData;
65 ret = MultiByteToWideChar(uCodePage, 0, pItemA->szString, -1,
66 pItemW->szString, _countof(pItemW->szString));
67 pItemW->szString[_countof(pItemW->szString) - 1] = UNICODE_NULL; // Avoid buffer overrun
68 return !!ret;
69}
70
71/* Convert Wide IME menu to ANSI */
72static BOOL
74 _In_ const IMEMENUITEMINFOW *pItemW,
75 _Out_ PIMEMENUITEMINFOA pItemA,
76 _In_ UINT uCodePage)
77{
78 INT ret;
79 pItemA->cbSize = pItemW->cbSize;
80 pItemA->fType = pItemW->fType;
81 pItemA->fState = pItemW->fState;
82 pItemA->wID = pItemW->wID;
83 pItemA->hbmpChecked = pItemW->hbmpChecked;
84 pItemA->hbmpUnchecked = pItemW->hbmpUnchecked;
85 pItemA->dwItemData = pItemW->dwItemData;
86 pItemA->hbmpItem = pItemW->hbmpItem;
87 ret = WideCharToMultiByte(uCodePage, 0, pItemW->szString, -1,
88 pItemA->szString, _countof(pItemA->szString), NULL, NULL);
89 pItemA->szString[_countof(pItemA->szString) - 1] = ANSI_NULL; // Avoid buffer overrun
90 return !!ret;
91}
92
93static PVOID
95 _In_ HDC hDC,
97 _In_ PBITMAPNODE pNode,
98 _In_ PIMEMENUINFO pView)
99{
100 BITMAPINFOHEADER *pBmih;
101 DWORD nodeExtraSize;
102 PVOID dibBitsPtr;
103 HBITMAP hbmpTemp;
105 DWORD totalNeeded;
106 int scanlines;
107
108 if (!hbmp)
109 return NULL;
110
111 pBmih = &pNode->bmih;
112 pBmih->biSize = sizeof(BITMAPINFOHEADER);
113 pBmih->biBitCount = 0;
114 if (!GetDIBits(hDC, hbmp, 0, 0, NULL, (BITMAPINFO*)pBmih, DIB_RGB_COLORS))
115 {
116 ERR("Invalid hbmp: %p\n", hbmp);
117 return NULL;
118 }
119
120 switch (pBmih->biBitCount)
121 {
122 case 16: case 32:
123 nodeExtraSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
124 break;
125 case 24:
126 nodeExtraSize = sizeof(BITMAPINFOHEADER);
127 break;
128 default:
129 nodeExtraSize = sizeof(BITMAPINFOHEADER);
130 nodeExtraSize += (1 << pBmih->biBitCount) * sizeof(RGBQUAD);
131 break;
132 }
133
134 totalNeeded = nodeExtraSize + pBmih->biSizeImage;
135 if ((PBYTE)pBmih + totalNeeded + sizeof(ULONG_PTR) > (PBYTE)pView + pView->dwBufferSize)
136 {
137 ERR("No more space\n");
138 return NULL;
139 }
140
141 dibBitsPtr = (PBYTE)pBmih + nodeExtraSize;
142 pNode->dibBitsPtr = (ULONG_PTR)dibBitsPtr; // Absolute address; convert to relative later
143
144 hbmpTemp = CreateCompatibleBitmap(hDC, pBmih->biWidth, labs(pBmih->biHeight));
145 if (!hbmpTemp)
146 {
147 ERR("Out of memory\n");
148 return NULL;
149 }
150
151 hbmpOld = SelectObject(hDC, hbmpTemp);
152 scanlines = GetDIBits(hDC, hbmp, 0, labs(pBmih->biHeight), dibBitsPtr,
155 DeleteObject(hbmpTemp);
156
157 if (!scanlines)
158 {
159 ERR("GetDIBits failed\n");
160 return NULL;
161 }
162
163 return (PBYTE)pBmih + nodeExtraSize + pBmih->biSizeImage;
164}
165
166static BOOL
168 PIMEMENUINFO pView,
170 DWORD dwType,
171 PIMEMENUITEMINFO lpImeParentMenu,
172 PIMEMENUITEMINFO lpImeMenuItems,
174{
175 ZeroMemory(pView, sizeof(*pView));
176 pView->dwVersion = 1;
178 pView->dwFlags = dwFlags;
179 pView->dwType = dwType;
180 pView->dwCount = dwSize / sizeof(IMEMENUITEMINFOW);
181
182 if ((dwSize == 0 || !lpImeMenuItems) && !lpImeParentMenu)
183 {
184 // No parents nor items
185 }
186 else if (lpImeParentMenu)
187 {
188 // There is parent
189 PIMEMENUITEMINFOW pParentSlot = (PIMEMENUITEMINFOW)(pView + 1);
190 RtlCopyMemory(pParentSlot, lpImeParentMenu, sizeof(IMEMENUITEMINFOW));
191 // Clear parent bitmaps (unused)
192 pParentSlot->hbmpChecked = NULL;
193 pParentSlot->hbmpUnchecked = NULL;
194 pParentSlot->hbmpItem = NULL;
195 // Offset (relative)
196 pView->dwParentOffset = sizeof(*pView);
197 pView->dwItemsOffset = sizeof(*pView) + sizeof(IMEMENUITEMINFOW);
198 }
199 else
200 {
201 // No parent but some items
202 pView->dwParentOffset = 0;
203 pView->dwItemsOffset = sizeof(*pView);
204 }
205
206 // SECURITY: Validate dwCount (ReactOS only)
207 return pView->dwItemsOffset + pView->dwCount * sizeof(IMEMENUITEMINFOW) <= pView->dwBufferSize;
208}
209
210static PBITMAPNODE
212 _In_ PIMEMENUINFO pView,
214{
215 PBITMAPNODE pListHead, pNode;
216 PVOID pNewEnd;
217 HWND hwndDesktop;
218 HDC hDC, hMemDC;
219
220 // Check bitmap caches
221 pNode = (PBITMAPNODE)pView->dwBitmapListOffset;
222 while (pNode)
223 {
224 if (pNode->hbmpCached == hbmp)
225 return pNode; // Cache hit
226 pNode = (PBITMAPNODE)pNode->dwNext;
227 }
228
229 // Boundary check
230 pNode = (PBITMAPNODE)pView->dwEndOffset;
231 if (!pNode ||
232 (PBYTE)pNode < (PBYTE)pView ||
233 (PBYTE)pNode >= (PBYTE)pView + pView->dwBufferSize ||
234 // ReactOS only:
235 (PBYTE)pNode + sizeof(BITMAPNODE) > (PBYTE)pView + pView->dwBufferSize)
236 {
237 ERR("Insufficient or incorrect space\n");
238 return NULL;
239 }
240
241 hwndDesktop = GetDesktopWindow();
242 hDC = GetDC(hwndDesktop);
243 if (!hDC)
244 {
245 ERR("GetDC failed\n");
246 return NULL;
247 }
248
249 hMemDC = CreateCompatibleDC(hDC);
250 if (!hMemDC)
251 {
252 ERR("CreateCompatibleDC failed\n");
253 ReleaseDC(hwndDesktop, hDC);
254 return NULL;
255 }
256 pListHead = (PBITMAPNODE)pView->dwBitmapListOffset;
257 pNode->dwNext = (ULONG_PTR)pListHead;
258
259 pNewEnd = Imm32WriteHBitmapToNode(hMemDC, hbmp, pNode, pView);
260
261 DeleteDC(hMemDC);
262 ReleaseDC(hwndDesktop, hDC);
263
264 if (!pNewEnd) // Failure
265 {
266 ERR("No more space\n");
267 pView->dwEndOffset = (ULONG_PTR)pNode;
268 pView->dwBitmapListOffset = pNode->dwNext;
269 return NULL;
270 }
271
272 pNode->hbmpCached = hbmp;
273 pNode->dwNext = (ULONG_PTR)pListHead;
274 pView->dwBitmapListOffset = (ULONG_PTR)pNode;
275 pView->dwEndOffset = (ULONG_PTR)pNewEnd;
276
277 return pNode;
278}
279
280static HBITMAP
282 _Inout_ PBITMAPNODE pNode)
283{
284 if (!pNode || !pNode->dibBitsPtr)
285 return NULL;
286
287 if (pNode->hbmpCached)
288 return pNode->hbmpCached;
289
291 if (!hDC)
292 return NULL;
293
294 HDC hCompatDC = CreateCompatibleDC(hDC);
295 if (!hCompatDC)
296 {
298 return NULL;
299 }
300
301 HBITMAP hbmp = CreateDIBitmap(hCompatDC, &pNode->bmih, CBM_INIT, (PVOID)pNode->dibBitsPtr,
302 (PBITMAPINFO)&pNode->bmih, DIB_RGB_COLORS);
303 pNode->hbmpCached = hbmp;
304
305 DeleteDC(hCompatDC);
307
308 return hbmp;
309}
310
311static BOOL
313{
314 PIMEMENUITEMINFOW pParent, pItems, pTempBuf;
315 DWORD i, dwCount, dwTempBufSize;
316 PBITMAPNODE pNode;
317 BOOL ret = FALSE;
318
319 if (pView->dwVersion != 1)
320 {
321 ERR("dwVersion mismatch: 0x%08lX\n", pView->dwVersion);
322 return FALSE;
323 }
324
325 if (pView->dwParentOffset)
326 {
327 // Convert relative to absolute
328 pParent = (PIMEMENUITEMINFOW)((PBYTE)pView + pView->dwParentOffset);
329 if ((PBYTE)pParent < (PBYTE)pView || (PBYTE)pParent >= (PBYTE)pView + pView->dwBufferSize)
330 {
331 ERR("Invalid dwParentOffset\n");
332 return FALSE;
333 }
335 }
336 else
337 {
338 pParent = NULL;
339 }
340
341 if (pView->dwItemsOffset)
342 {
343 // Convert relative to absolute
344 pItems = (PIMEMENUITEMINFOW)((PBYTE)pView + pView->dwItemsOffset);
345 if ((PBYTE)pItems < (PBYTE)pView || (PBYTE)pItems >= (PBYTE)pView + pView->dwBufferSize)
346 {
347 ERR("Invalid dwItemsOffset\n");
348 return FALSE;
349 }
351 }
352 else
353 {
354 pItems = NULL;
355 }
356
357 // Allocate items buffer
358 if (pView->dwCount > 0)
359 {
360 dwTempBufSize = pView->dwCount * sizeof(IMEMENUITEMINFOW);
361 pTempBuf = ImmLocalAlloc(0, dwTempBufSize);
362 if (!pTempBuf)
363 {
364 ERR("Out of memory\n");
365 return FALSE;
366 }
367 }
368 else
369 {
370 pTempBuf = NULL;
371 dwTempBufSize = 0;
372 }
373
374 dwCount = ImmGetImeMenuItemsW(hIMC, pView->dwFlags, pView->dwType, pParent,
375 pTempBuf, dwTempBufSize);
376 pView->dwCount = dwCount;
377
378 if (dwCount == 0) // No items?
379 {
380 if (pTempBuf)
381 ImmLocalFree(pTempBuf);
382
383 ret = TRUE;
384 goto ConvertBack;
385 }
386
387 if (!pTempBuf)
388 {
389 ret = TRUE;
390 goto ConvertBack;
391 }
392
393 pView->dwBitmapListOffset = 0;
394
395 // Compute end of items buffer and ensure it stays within the mapped buffer
396 {
397 PBYTE pBufferEnd = (PBYTE)pView + pView->dwBufferSize;
398 PBYTE pItemsEnd = (PBYTE)pItems + dwCount * sizeof(IMEMENUITEMINFOW);
399 if (pItemsEnd > pBufferEnd)
400 {
401 ret = FALSE;
402 goto FreeAndCleanup;
403 }
404 pView->dwEndOffset = (ULONG_PTR)pItemsEnd;
405 }
406
407 // Serialize items
408 for (i = 0; i < dwCount; i++)
409 {
410 PIMEMENUITEMINFOW pSrc = &pTempBuf[i];
411 PIMEMENUITEMINFOW pDest = pItems + i;
412 *pDest = *pSrc;
413
414 // Serialize hbmpChecked
415 if (pSrc->hbmpChecked)
416 {
417 pNode = Imm32SerializeBitmap(pView, pSrc->hbmpChecked);
418 if (!pNode)
419 goto FreeAndCleanup;
420 pDest->hbmpChecked = (HBITMAP)(ULONG_PTR)pNode; // Absolute pointer
421 }
422 else
423 {
424 pDest->hbmpChecked = NULL;
425 }
426
427 // Serialize hbmpUnchecked
428 if (pSrc->hbmpUnchecked)
429 {
430 pNode = Imm32SerializeBitmap(pView, pSrc->hbmpUnchecked);
431 if (!pNode)
432 goto FreeAndCleanup;
433 pDest->hbmpUnchecked = (HBITMAP)(ULONG_PTR)pNode;
434 }
435 else
436 {
437 pDest->hbmpUnchecked = NULL;
438 }
439
440 // Serialize hbmpItem
441 if (pSrc->hbmpItem)
442 {
443 pNode = Imm32SerializeBitmap(pView, pSrc->hbmpItem);
444 if (!pNode)
445 goto FreeAndCleanup;
446 pDest->hbmpItem = (HBITMAP)(ULONG_PTR)pNode;
447 }
448 else
449 {
450 pDest->hbmpItem = NULL;
451 }
452 }
453
454 ret = TRUE;
455
456FreeAndCleanup:
457 ImmLocalFree(pTempBuf);
458
459ConvertBack:
460 // Convert dwItemsOffset to relative
461 if (pView->dwItemsOffset)
462 pView->dwItemsOffset = pView->dwItemsOffset - (ULONG_PTR)pView;
463
464 if (pView->dwCount > 0 && pItems)
465 {
466 // Convert bitmaps to relative
467 for (i = 0; i < pView->dwCount; i++)
468 {
469 PIMEMENUITEMINFOW pItem = pItems + i;
470 if (pItem->hbmpChecked)
471 pItem->hbmpChecked = (HBITMAP)((PBYTE)pItem->hbmpChecked - (PBYTE)pView);
472 if (pItem->hbmpUnchecked)
473 pItem->hbmpUnchecked = (HBITMAP)((PBYTE)pItem->hbmpUnchecked - (PBYTE)pView);
474 if (pItem->hbmpItem)
475 pItem->hbmpItem = (HBITMAP)((PBYTE)pItem->hbmpItem - (PBYTE)pView);
476 }
477 }
478
479 // Convert dwBitmapListOffset to relative
480 if (pView->dwBitmapListOffset)
481 {
483 pView->dwBitmapListOffset = (ULONG_PTR)pCur - (ULONG_PTR)pView;
484
485 while (pCur)
486 {
487 PBITMAPNODE pNext = (PBITMAPNODE)pCur->dwNext;
488
489 if (pCur->dibBitsPtr)
490 pCur->dibBitsPtr = pCur->dibBitsPtr - (ULONG_PTR)pView;
491 if (pCur->dwNext)
492 pCur->dwNext = (ULONG_PTR)pNext - (ULONG_PTR)pView;
493
494 pCur = pNext;
495 }
496 }
497
498 // Convert dwParentOffset to relative
499 if (pView->dwParentOffset && (PBYTE)pView->dwParentOffset >= (PBYTE)pView)
500 pView->dwParentOffset = pView->dwParentOffset - (ULONG_PTR)pView;
501
502 return ret;
503}
504
505static DWORD
507 _In_ PIMEMENUINFO pView,
508 _Out_opt_ PIMEMENUITEMINFOW lpImeMenuItems,
510{
511 DWORD i, dwCount;
512 PBYTE pViewBase = (PBYTE)pView;
513 PBITMAPNODE pNode;
514 PIMEMENUITEMINFOW pItemsBase;
515
516 dwCount = pView->dwCount;
517
518 if (!lpImeMenuItems)
519 return dwCount;
520
521 if (dwCount == 0)
522 return 0;
523
524 // SECURITY: Validate dwSize (ReactOS only)
525 dwCount = min(dwCount, dwSize / sizeof(IMEMENUITEMINFOW));
526
527 if (pView->dwBitmapListOffset)
528 {
529 PBITMAPNODE pCur = (PBITMAPNODE)(pViewBase + pView->dwBitmapListOffset);
530 pView->dwBitmapListOffset = (ULONG_PTR)pCur;
531
532 while (pCur)
533 {
534 PBITMAPNODE pNextCur;
535
536 pCur->hbmpCached = NULL;
537
538 // dibBitsPtr: relative to absolute
539 if (pCur->dibBitsPtr)
540 pCur->dibBitsPtr = (ULONG_PTR)(pViewBase + pCur->dibBitsPtr);
541
542 // dwNext: relative to absolute
543 if (pCur->dwNext)
544 {
545 pNextCur = (PBITMAPNODE)(pViewBase + pCur->dwNext);
546 if ((PBYTE)pNextCur < pViewBase ||
547 (PBYTE)pNextCur >= pViewBase + pView->dwBufferSize)
548 {
549 ERR("Invalid dwNext\n");
550 return 0;
551 }
552 pCur->dwNext = (ULONG_PTR)pNextCur;
553 pCur = pNextCur;
554 }
555 else
556 {
557 pCur->dwNext = 0;
558 pCur = NULL;
559 }
560 }
561 }
562
563 // dwItemsOffset: relative to absolute
564 if (pView->dwItemsOffset)
565 {
566 pItemsBase = (PIMEMENUITEMINFOW)(pViewBase + pView->dwItemsOffset);
567 // Boundary check: base pointer must be inside the view
568 if ((PBYTE)pItemsBase < pViewBase || (PBYTE)pItemsBase >= pViewBase + pView->dwBufferSize)
569 return 0;
570
571 // Boundary check (ReactOS only): ensure the whole items array fits inside the view
572 if (dwCount > 0)
573 {
574 SIZE_T offsetFromBase = (SIZE_T)((PBYTE)pItemsBase - pViewBase);
575 SIZE_T available = (SIZE_T)pView->dwBufferSize - offsetFromBase;
576 SIZE_T needed = (SIZE_T)dwCount * sizeof(IMEMENUITEMINFOW);
577
578 if (available < needed)
579 return 0;
580 }
581
582 pView->dwItemsOffset = (ULONG_PTR)pItemsBase;
583 }
584 else
585 {
586 return 0;
587 }
588
589 // Bitmap offsets: relative to absolute
590 for (i = 0; i < dwCount; i++)
591 {
592 PIMEMENUITEMINFOW pItem =
593 (PIMEMENUITEMINFOW)((PBYTE)pView->dwItemsOffset + i * sizeof(IMEMENUITEMINFOW));
594
595 // hbmpChecked
596 if (pItem->hbmpChecked)
597 {
598 PBITMAPNODE pN = (PBITMAPNODE)(pViewBase + (ULONG_PTR)pItem->hbmpChecked);
599 if ((PBYTE)pN < pViewBase || (PBYTE)pN >= pViewBase + pView->dwBufferSize)
600 {
601 ERR("Invalid hbmpChecked\n");
602 return 0;
603 }
604 pItem->hbmpChecked = (HBITMAP)(ULONG_PTR)pN;
605 }
606
607 // hbmpUnchecked
608 if (pItem->hbmpUnchecked)
609 {
610 PBITMAPNODE pN = (PBITMAPNODE)(pViewBase + (ULONG_PTR)pItem->hbmpUnchecked);
611 if ((PBYTE)pN < pViewBase || (PBYTE)pN >= pViewBase + pView->dwBufferSize)
612 {
613 ERR("Invalid hbmpUnchecked\n");
614 return 0;
615 }
616 pItem->hbmpUnchecked = (HBITMAP)(ULONG_PTR)pN;
617 }
618
619 // hbmpItem
620 if (pItem->hbmpItem)
621 {
622 PBITMAPNODE pN = (PBITMAPNODE)(pViewBase + (ULONG_PTR)pItem->hbmpItem);
623 if ((PBYTE)pN < pViewBase || (PBYTE)pN >= pViewBase + pView->dwBufferSize)
624 {
625 ERR("Invalid hbmpItem\n");
626 return 0;
627 }
628 pItem->hbmpItem = (HBITMAP)(ULONG_PTR)pN;
629 }
630 }
631
632 // De-serialize items
633 for (i = 0; i < dwCount; i++)
634 {
635 PIMEMENUITEMINFOW pSrc =
636 (PIMEMENUITEMINFOW)((PBYTE)pView->dwItemsOffset + i * sizeof(IMEMENUITEMINFOW));
637 PIMEMENUITEMINFOW pDst = &lpImeMenuItems[i];
638
639 // Copy scalar fields (excluding HBITMAP fields)
640 pDst->cbSize = pSrc->cbSize;
641 pDst->fType = pSrc->fType;
642 pDst->fState = pSrc->fState;
643 pDst->wID = pSrc->wID;
644 pDst->dwItemData = pSrc->dwItemData;
645
646 // Copy szString
647 StringCbCopyW(pDst->szString, sizeof(pDst->szString), pSrc->szString);
648
649 // De-serialize hbmpChecked
650 pNode = (PBITMAPNODE)(ULONG_PTR)pSrc->hbmpChecked;
651 pDst->hbmpChecked = Imm32DeserializeBitmap(pNode);
652
653 // De-serialize hbmpUnchecked
654 pNode = (PBITMAPNODE)(ULONG_PTR)pSrc->hbmpUnchecked;
655 pDst->hbmpUnchecked = Imm32DeserializeBitmap(pNode);
656
657 // De-serialize hbmpItem
658 pNode = (PBITMAPNODE)(ULONG_PTR)pSrc->hbmpItem;
659 pDst->hbmpItem = Imm32DeserializeBitmap(pNode);
660 }
661
662 return dwCount;
663}
664
665static DWORD
667 _In_ HIMC hIMC,
669 _In_ DWORD dwType,
670 _Inout_opt_ PVOID lpImeParentMenu,
671 _Out_writes_bytes_opt_(dwSize) PVOID lpImeMenuItems,
673{
674 HWND hwndIme;
675 HANDLE hMapping = NULL;
676 PIMEMENUINFO pView = NULL;
677 DWORD dwCount = 0;
678
679 // Get IME window
681 if (!hwndIme || !IsWindow(hwndIme))
682 return 0;
683
685
686 // Create a file mapping
689 if (!hMapping)
690 goto Cleanup;
691
692 // Map view of file mapping
693 pView = MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
694 if (!pView)
695 goto Cleanup;
696
697 if (!Imm32InitImeMenuView(pView, dwFlags, dwType, lpImeParentMenu, lpImeMenuItems, dwSize))
698 goto Cleanup;
699
700 // WM_IME_SYSTEM:IMS_GETIMEMENU will invoke ImmPutImeMenuItemsIntoMappedFile to serialize
701 if (!SendMessageW(hwndIme, WM_IME_SYSTEM, IMS_GETIMEMENU, (LPARAM)hIMC))
702 goto Cleanup;
703
704 dwCount = pView->dwCount;
705
706 if (!lpImeMenuItems)
707 goto Cleanup;
708
709 // De-serialize IME menu
710 dwCount = Imm32DeserializeImeMenu(pView, lpImeMenuItems, dwSize);
711
712Cleanup:
713 if (pView)
714 UnmapViewOfFile(pView);
715 if (hMapping)
716 CloseHandle(hMapping);
717
719
720 return dwCount;
721}
722
723/***********************************************************************
724 * ImmPutImeMenuItemsIntoMappedFile (IMM32.@)
725 *
726 * Called from user32.dll to transport the IME menu items by using a
727 * file mapping object. This function is provided for WM_IME_SYSTEM:IMS_GETIMEMENU
728 * handling.
729 */
732{
733 /* Open the existing file mapping */
735 if (!hMapping)
736 {
737 ERR("OpenFileMappingW failed\n");
738 return FALSE;
739 }
740
741 PIMEMENUINFO pView = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
742 if (!pView)
743 {
744 ERR("MapViewOfFile failed\n");
745 CloseHandle(hMapping);
746 return FALSE;
747 }
748
749 BOOL ret = Imm32SerializeImeMenu(hIMC, pView);
750 UnmapViewOfFile(pView);
751 CloseHandle(hMapping);
752 return ret;
753}
754
755/* Absorbs the differences between ANSI and Wide */
756static DWORD
758 _In_ HIMC hIMC,
760 _In_ DWORD dwType,
761 _Inout_opt_ PVOID lpImeParentMenu,
762 _Out_writes_bytes_opt_(dwSize) PVOID lpImeMenuItems,
764 _In_ BOOL bTargetIsAnsi)
765{
766 DWORD ret = 0, iItem;
767
768 if (!hIMC)
769 {
770 ERR("!hIMC\n");
771 return 0;
772 }
773
774 /* Get input process ID */
776 if (!dwProcessId)
777 {
778 ERR("!dwProcessId\n");
779 return 0;
780 }
781
782 if (dwProcessId != GetCurrentProcessId()) /* Cross process? */
783 {
784 if (bTargetIsAnsi)
785 {
786 ERR("ImmGetImeMenuItemsA cannot cross process boundary\n");
787 return 0;
788 }
789
790 /* Transport the IME menu items, using file mapping */
791 return ImmGetImeMenuItemsInterProcess(hIMC, dwFlags, dwType, lpImeParentMenu,
792 lpImeMenuItems, dwSize);
793 }
794
795 PINPUTCONTEXT pIC = ImmLockIMC(hIMC);
796 if (!pIC)
797 {
798 ERR("!pIC\n");
799 return 0;
800 }
801
802 /* Get input thread ID */
804 if (!dwThreadId)
805 {
806 ERR("!dwThreadId\n");
807 ImmUnlockIMC(hIMC);
808 return 0;
809 }
810
811 /* Get IME interface */
813 PIMEDPI pImeDpi = ImmLockImeDpi(hKL);
814 if (!pImeDpi)
815 {
816 ERR("!pImeDpi\n");
817 ImmUnlockIMC(hIMC);
818 return 0;
819 }
820
821 /* ImeGetImeMenuItems is optional */
822 if (!pImeDpi->ImeGetImeMenuItems)
823 {
824 WARN("ImeGetImeMenuItems is not available (optional).\n");
825 ImmUnlockImeDpi(pImeDpi);
826 ImmUnlockIMC(hIMC);
827 return 0;
828 }
829
830 /* Is the IME ANSI? */
831 BOOL bImcIsAnsi = Imm32IsImcAnsi(hIMC);
832
833 IMEMENUITEMINFOA ParentA, *pItemA;
834 IMEMENUITEMINFOW ParentW, *pItemW;
835 PVOID pNewItems = NULL, pNewParent = NULL;
836
837 /* Are text types (ANSI/Wide) different between IME and target? */
838 if (bImcIsAnsi != bTargetIsAnsi)
839 {
840 DWORD cbTotal;
841 if (bTargetIsAnsi)
842 {
843 /* Convert the parent */
844 if (lpImeParentMenu)
845 {
846 Imm32ImeMenuAnsiToWide(lpImeParentMenu, &ParentW, pImeDpi->uCodePage, TRUE);
847 pNewParent = &ParentW;
848 }
849
850 /* Allocate buffer for new items */
851 if (lpImeMenuItems)
852 {
853 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOA)) * sizeof(IMEMENUITEMINFOW));
854 pNewItems = ImmLocalAlloc(0, cbTotal);
855 if (!pNewItems)
856 {
857 ERR("!pNewItems\n");
858 goto Quit;
859 }
860 }
861 }
862 else
863 {
864 /* Convert the parent */
865 if (lpImeParentMenu)
866 {
867 Imm32ImeMenuWideToAnsi(lpImeParentMenu, &ParentA, pImeDpi->uCodePage);
868 pNewParent = &ParentA;
869 }
870
871 /* Allocate buffer for new items */
872 if (lpImeMenuItems)
873 {
874 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOW)) * sizeof(IMEMENUITEMINFOA));
875 pNewItems = ImmLocalAlloc(0, cbTotal);
876 if (!pNewItems)
877 {
878 ERR("!pNewItems\n");
879 goto Quit;
880 }
881 }
882 }
883 }
884 else
885 {
886 /* Get the items directly */
887 pNewItems = lpImeMenuItems;
888 pNewParent = lpImeParentMenu;
889 }
890
891 /* Get IME menu items from the IME */
892 ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize);
893 if (!ret)
894 {
895 ERR("ImeGetImeMenuItems failed\n");
896 goto Quit;
897 }
898
899 if (!lpImeMenuItems)
900 goto Quit;
901
902 if (bImcIsAnsi != bTargetIsAnsi) /* Are text types different? */
903 {
904 if (bTargetIsAnsi)
905 {
906 /* Convert the parent */
907 if (pNewParent)
908 Imm32ImeMenuWideToAnsi(pNewParent, lpImeParentMenu, pImeDpi->uCodePage);
909
910 /* Convert the items */
911 pItemW = pNewItems;
912 pItemA = lpImeMenuItems;
913 for (iItem = 0; iItem < ret; ++iItem, ++pItemW, ++pItemA)
914 {
915 Imm32ImeMenuWideToAnsi(pItemW, pItemA, pImeDpi->uCodePage);
916 }
917 }
918 else
919 {
920 /* Convert the parent */
921 if (pNewParent)
922 Imm32ImeMenuAnsiToWide(pNewParent, lpImeParentMenu, pImeDpi->uCodePage, TRUE);
923
924 /* Convert the items */
925 pItemA = pNewItems;
926 pItemW = lpImeMenuItems;
927 for (iItem = 0; iItem < dwSize; ++iItem, ++pItemA, ++pItemW)
928 {
929 Imm32ImeMenuAnsiToWide(pItemA, pItemW, pImeDpi->uCodePage, TRUE);
930 }
931 }
932 }
933
934Quit:
935 if (pNewItems != lpImeMenuItems)
936 ImmLocalFree(pNewItems);
937 ImmUnlockImeDpi(pImeDpi);
938 ImmUnlockIMC(hIMC);
939 return ret;
940}
941
942/***********************************************************************
943 * ImmGetImeMenuItemsA (IMM32.@)
944 */
947 _In_ HIMC hIMC,
949 _In_ DWORD dwType,
950 _Inout_opt_ PIMEMENUITEMINFOA lpImeParentMenu,
951 _Out_writes_bytes_opt_(dwSize) PIMEMENUITEMINFOA lpImeMenu,
953{
954 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
955 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize);
956 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, TRUE);
957}
958
959/***********************************************************************
960 * ImmGetImeMenuItemsW (IMM32.@)
961 */
964 _In_ HIMC hIMC,
966 _In_ DWORD dwType,
967 _Inout_opt_ PIMEMENUITEMINFOW lpImeParentMenu,
968 _Out_writes_bytes_opt_(dwSize) PIMEMENUITEMINFOW lpImeMenu,
970{
971 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
972 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize);
973 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, FALSE);
974}
static HDC hDC
Definition: 3dtext.c:33
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
HBITMAP hbmp
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
DWORD HIMC
Definition: dimm.idl:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2336
#define CloseHandle
Definition: compat.h:739
#define UnmapViewOfFile
Definition: compat.h:746
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
HANDLE HWND
Definition: compat.h:19
#define FILE_MAP_READ
Definition: compat.h:776
#define WideCharToMultiByte
Definition: compat.h:111
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
_ACRTIMP __msvcrt_long __cdecl labs(__msvcrt_long)
Definition: math.c:680
static const WCHAR Cleanup[]
Definition: register.c:80
ULONG RGBQUAD
Definition: precomp.h:47
return ret
Definition: mutex.c:146
#define ULONG_PTR
Definition: config.h:101
DWORD dwThreadId
Definition: fdebug.c:31
HANDLE NTAPI OpenFileMappingW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: filemap.c:297
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
SINGLE_LIST_ENTRY * pCur
FxObject * pParent
Definition: fxdpcapi.cpp:86
pKey DeleteObject()
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
RTL_CRITICAL_SECTION gcsImeDpi
Definition: ime.c:16
#define IMS_GETIMEMENU
Definition: imm32_undoc.h:51
PIMEDPI WINAPI ImmLockImeDpi(_In_ HKL hKL)
Definition: ime.c:531
#define WM_IME_SYSTEM
Definition: imm32_undoc.h:32
VOID WINAPI ImmUnlockImeDpi(_Inout_opt_ PIMEDPI pImeDpi)
Definition: ime.c:561
LPINPUTCONTEXT WINAPI ImmLockIMC(_In_ HIMC hIMC)
Definition: imm.c:1080
BOOL WINAPI ImmUnlockIMC(_In_ HIMC hIMC)
Definition: imm.c:1090
DWORD_PTR NTAPI NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
Definition: ime.c:1880
JSAMPARRAY scanlines
Definition: jpeglib.h:1016
if(dx< 0)
Definition: linetemp.h:194
HANDLE hbmpOld
Definition: magnifier.c:54
#define ZeroMemory
Definition: minwinbase.h:31
LONG_PTR LPARAM
Definition: minwindef.h:175
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
static int int const SCRIPT_CONTROL const SCRIPT_STATE SCRIPT_ITEM * pItems
Definition: usp10.c:62
#define min(a, b)
Definition: monoChain.cc:55
UINT_PTR HKL
Definition: msctf.idl:125
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_bytes_opt_(s)
Definition: no_sal2.h:228
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define DWORD
Definition: nt_native.h:44
#define UNICODE_NULL
#define ANSI_NULL
BYTE * PBYTE
Definition: pedump.c:66
_In_ DWORD dwProcessId
Definition: shlwapi.h:193
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
DWORD biSizeImage
Definition: amvideo.idl:36
UINT uCodePage
Definition: imm32_undoc.h:97
BITMAPINFOHEADER bmih
Definition: imemenu.c:40
HBITMAP hbmpCached
Definition: imemenu.c:38
ULONG_PTR dibBitsPtr
Definition: imemenu.c:39
ULONG_PTR dwNext
Definition: imemenu.c:37
ULONG_PTR dwBitmapListOffset
Definition: imemenu.c:31
DWORD dwVersion
Definition: imemenu.c:24
DWORD dwCount
Definition: imemenu.c:30
ULONG_PTR dwParentOffset
Definition: imemenu.c:28
DWORD dwFlags
Definition: imemenu.c:26
ULONG_PTR dwItemsOffset
Definition: imemenu.c:29
DWORD dwBufferSize
Definition: imemenu.c:25
DWORD dwType
Definition: imemenu.c:27
ULONG_PTR dwEndOffset
Definition: imemenu.c:32
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
@ QIC_DEFAULTWINDOWIME
Definition: undocuser.h:414
@ QIC_INPUTTHREADID
Definition: undocuser.h:413
@ QIC_INPUTPROCESSID
Definition: undocuser.h:412
struct tagIMEMENUINFO IMEMENUINFO
static DWORD Imm32DeserializeImeMenu(_In_ PIMEMENUINFO pView, _Out_opt_ PIMEMENUITEMINFOW lpImeMenuItems, _In_ DWORD dwSize)
Definition: imemenu.c:506
DWORD WINAPI ImmGetImeMenuItemsW(_In_ HIMC hIMC, _In_ DWORD dwFlags, _In_ DWORD dwType, _Inout_opt_ PIMEMENUITEMINFOW lpImeParentMenu, _Out_writes_bytes_opt_(dwSize) PIMEMENUITEMINFOW lpImeMenu, _In_ DWORD dwSize)
Definition: imemenu.c:963
static HBITMAP Imm32DeserializeBitmap(_Inout_ PBITMAPNODE pNode)
Definition: imemenu.c:281
struct tagBITMAPNODE BITMAPNODE
#define IMEMENUINFO_MAPPING_NAME
Definition: imemenu.c:19
static DWORD ImmGetImeMenuItemsAW(_In_ HIMC hIMC, _In_ DWORD dwFlags, _In_ DWORD dwType, _Inout_opt_ PVOID lpImeParentMenu, _Out_writes_bytes_opt_(dwSize) PVOID lpImeMenuItems, _In_ DWORD dwSize, _In_ BOOL bTargetIsAnsi)
Definition: imemenu.c:757
BOOL WINAPI ImmPutImeMenuItemsIntoMappedFile(_In_ HIMC hIMC)
Definition: imemenu.c:731
static BOOL Imm32InitImeMenuView(PIMEMENUINFO pView, DWORD dwFlags, DWORD dwType, PIMEMENUITEMINFO lpImeParentMenu, PIMEMENUITEMINFO lpImeMenuItems, DWORD dwSize)
Definition: imemenu.c:167
static BOOL Imm32SerializeImeMenu(HIMC hIMC, PIMEMENUINFO pView)
Definition: imemenu.c:312
static PVOID Imm32WriteHBitmapToNode(_In_ HDC hDC, _In_ HBITMAP hbmp, _In_ PBITMAPNODE pNode, _In_ PIMEMENUINFO pView)
Definition: imemenu.c:94
struct tagIMEMENUINFO * PIMEMENUINFO
static DWORD ImmGetImeMenuItemsInterProcess(_In_ HIMC hIMC, _In_ DWORD dwFlags, _In_ DWORD dwType, _Inout_opt_ PVOID lpImeParentMenu, _Out_writes_bytes_opt_(dwSize) PVOID lpImeMenuItems, _In_ DWORD dwSize)
Definition: imemenu.c:666
static PBITMAPNODE Imm32SerializeBitmap(_In_ PIMEMENUINFO pView, _In_ HBITMAP hbmp)
Definition: imemenu.c:211
#define IMEMENUINFO_BUFFER_SIZE
Definition: imemenu.c:18
DWORD WINAPI ImmGetImeMenuItemsA(_In_ HIMC hIMC, _In_ DWORD dwFlags, _In_ DWORD dwType, _Inout_opt_ PIMEMENUITEMINFOA lpImeParentMenu, _Out_writes_bytes_opt_(dwSize) PIMEMENUITEMINFOA lpImeMenu, _In_ DWORD dwSize)
Definition: imemenu.c:946
struct tagBITMAPNODE * PBITMAPNODE
static BOOL Imm32ImeMenuWideToAnsi(_In_ const IMEMENUITEMINFOW *pItemW, _Out_ PIMEMENUITEMINFOA pItemA, _In_ UINT uCodePage)
Definition: imemenu.c:73
static BOOL Imm32ImeMenuAnsiToWide(_In_ const IMEMENUITEMINFOA *pItemA, _Out_ PIMEMENUITEMINFOW pItemW, _In_ UINT uCodePage, _In_ BOOL bBitmap)
Definition: imemenu.c:47
#define ImmLocalFree(lpData)
Definition: precomp.h:102
BOOL Imm32IsImcAnsi(HIMC hIMC)
Definition: utils.c:85
LPVOID ImmLocalAlloc(_In_ DWORD dwFlags, _In_ DWORD dwBytes)
Definition: utils.c:275
#define FILE_MAP_WRITE
Definition: winbase.h:156
#define FILE_MAP_ALL_ACCESS
Definition: winbase.h:158
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1156
#define WINAPI
Definition: msvc.h:6
#define DIB_RGB_COLORS
Definition: wingdi.h:367
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
#define CBM_INIT
Definition: wingdi.h:365
BOOL WINAPI DeleteDC(_In_ HDC)
HBITMAP WINAPI CreateDIBitmap(_In_ HDC hdc, _In_opt_ const BITMAPINFOHEADER *pbmih, _In_ DWORD fdwInit, _In_opt_ const VOID *pvInit, _In_opt_ const BITMAPINFO *pbmi, _In_ UINT uUsage)
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
BOOL WINAPI IsWindow(_In_opt_ HWND)
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:628
HDC WINAPI GetDC(_In_opt_ HWND)
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)