LPWSTR WINAPI CharNextW( LPCWSTR lpwCurrentChar) { WORD ctype3info; if (*lpwCurrentChar) { // // Examine each code element. Skip all combining elements. // while (*(++lpwCurrentChar)) { if (!GetStringTypeW( CT_CTYPE3, lpwCurrentChar, 1, &ctype3info)) { /* * GetStringTypeW failed! The caller is not expecting failure, * CharNextW does not have a failure indicator, so just return * a pointer to the character we couldn't analyze. */ RIPMSG2(RIP_WARNING, "CharNextW failed, L'\\x%.4x' at %#p", *lpwCurrentChar, lpwCurrentChar); break; } if (!((ctype3info & C3_NONSPACING) && (!(ctype3info & C3_ALPHA)))) { break; } } } return (LPWSTR)lpwCurrentChar; }
VOID CliGetPreloadKeyboardLayouts(FE_KEYBOARDS* pFeKbds) { UINT i; WCHAR szPreLoadee[4]; // up to 999 preloads WCHAR lpszName[KL_NAMELENGTH]; UNICODE_STRING UnicodeString; HKL hkl; for (i = 1; i < 1000; i++) { wsprintf(szPreLoadee, L"%d", i); if ((GetPrivateProfileStringW( L"Preload", szPreLoadee, L"", // default = NULL lpszName, // output buffer KL_NAMELENGTH, L"keyboardlayout.ini") == -1 ) || (*lpszName == L'\0')) { break; } RtlInitUnicodeString(&UnicodeString, lpszName); RtlUnicodeStringToInteger(&UnicodeString, 16L, (PULONG)&hkl); RIPMSG2(RIP_VERBOSE, "PreLoaded HKL(%d): %08X\n", i, hkl); // // Set language flags. By its definition, LOWORD(hkl) is LANGID // SetFeKeyboardFlags(LOWORD(HandleToUlong(hkl)), pFeKbds); } }
VOID vMoveFileFromSystemToFontsDir(WCHAR *pwcFile) { WCHAR awcTmpBuf[MAX_PATH]; WCHAR awcTmp[MAX_PATH]; FLONG fl; WCHAR *pwcTmp; #if DBG BOOL bOk; #endif if (bMakePathNameW(awcTmp, pwcFile,NULL, &fl)) { // If the font is in the system subdirectory we will just move it // to the fonts subdirectory. The path in the registry is relative // and we will leave it alone. if ( (fl & (FONT_IN_SYSTEM_DIR | FONT_RELATIVE_PATH)) == (FONT_IN_SYSTEM_DIR | FONT_RELATIVE_PATH) ) { // find the bare file part, this is what will be written // in the registry pwcTmp = &awcTmp[wcslen(awcTmp) - 1]; while ((pwcTmp >= awcTmp) && (*pwcTmp != L'\\') && (*pwcTmp != L':')) pwcTmp--; if (pwcTmp > awcTmp) pwcTmp++; // need to move the font to fonts dir, can reuse the // buffer on the stack to build the full destination path wcscpy(awcTmpBuf, gpwcFontsDir); lstrcatW(awcTmpBuf, L"\\"); lstrcatW(awcTmpBuf, pwcTmp); // note that MoveFile should succeed, for if there was // a font file of the same file name in %windir%\fonts dir // we would not have been in this code path. #if DBG bOk = #endif MoveFileW(awcTmp, awcTmpBuf); RIPMSG3(RIP_VERBOSE, "move %ws to %ws %s", awcTmp, awcTmpBuf, (bOk) ? "succeeded" : "failed"); } #if DBG else { RIPMSG2(RIP_WARNING, "File %ws not in system directory, fl = 0x%lx\n", awcTmp, fl); } #endif } #if DBG else { RIPMSG1(RIP_WARNING, "Could not locate %ws", pwcFile); } #endif }
VOID vProcessFontEntry( HKEY hkey, WCHAR *pwcValueName, WCHAR *pwcFileName ) { BOOL bFot = FALSE; WCHAR awcTTF[MAX_PATH]; WCHAR awcTmpBuf[MAX_PATH]; WCHAR *pwcTTF; FLONG fl, fl2; FLONG flEmbed; DWORD dwPidTid; if (bCheckFontEntry(pwcValueName, EXT_TRUETYPE)) { // This is a tt entry, either .fot or .ttf if (bFot = bCheckFontEntry(pwcFileName,EXT_FOT)) { // this is an .fot entry, must find ttf pointed to by .fot, // but first must get the full path to the .fot file // for cGetTTFFromFOT routine expects it. We will also need // the full path to the .fot file so that we can delete it // eventually. if (bMakePathNameW(awcTmpBuf, pwcFileName,NULL, &fl2)) { if (cGetTTFFromFOT(awcTmpBuf, MAX_PATH, awcTTF, &fl, &flEmbed, &dwPidTid) && !(fl & FONT_ISNOT_FOT)) { // fix the entry to point to .ttf file. At this point // awcTTF points to the FULL path to the .ttf file. // However, we will only need a relative path to the // .ttf file, when the .ttf file is in the %windir%\system // or %windir%\fonts directories. In case the file is in the // %windir%\system directory we shall copy it to %windir%\fonts // directory and write the relative path to the registry. // In case it is in the %windir%\fonts directory we do not // touch the file and also just write the relative path to the // registry. In any other case we just write the full .ttf // path to the registry. // first delete the .fot file, it is no longer needed if (bFot && !gbWin31Upgrade) { UserVerify(DeleteFileW(awcTmpBuf)); } if ((fl & (FONT_IN_FONTS_DIR | FONT_IN_SYSTEM_DIR)) == 0) { // if ttf file is not in either the system or the fonts // directories, just write the full path to the registry pwcTTF = awcTTF; } else { // find the bare file part, this is what will be written // in the registry pwcTTF = &awcTTF[wcslen(awcTTF) - 1]; while ((pwcTTF >= awcTTF) && (*pwcTTF != L'\\') && (*pwcTTF != L':')) pwcTTF--; pwcTTF++; if (fl & FONT_IN_SYSTEM_DIR) { // need to move the ttf to fonts dir, can reuse the // buffer on the stack: wcscpy(awcTmpBuf, gpwcFontsDir); lstrcatW(awcTmpBuf, L"\\"); lstrcatW(awcTmpBuf, pwcTTF); // note that MoveFile should succeed, for if there was // a ttf file of the same file name in %windir%\fonts dir // we would not have been in this code path. RIPMSG2(RIP_VERBOSE, "Moving %ws to %ws", awcTTF, awcTmpBuf); if (!gbWin31Upgrade) { UserVerify(MoveFileW(awcTTF, awcTmpBuf)); } else { // Boolean value TRUE means "do not copy if target exists" UserVerify(CopyFileW(awcTTF, awcTmpBuf, TRUE)); } } } RIPMSG2(RIP_VERBOSE, "writing to the registry:\n %ws=%ws", pwcValueName, pwcTTF); UserVerify(ERROR_SUCCESS == RegSetValueExW( hkey, // here is the key pwcValueName, 0, REG_SZ, (CONST BYTE*) pwcTTF, (DWORD)((wcslen(pwcTTF)+1) * sizeof(WCHAR)))); } #ifdef DEBUG else { RIPMSG1(RIP_WARNING, "Could not locate ttf pointed to by %ws", awcTmpBuf); } #endif } #ifdef DEBUG else { RIPMSG1(RIP_WARNING, "Could not locate .fot: %ws", pwcFileName); } #endif } } else { // not a true type case. little bit simpler, // we will use awcTTF buffer for the full path name, and pwcTTF // as local variable even though these TTF names are misnomer // for these are not tt fonts if (bMakePathNameW(awcTTF, pwcFileName,NULL, &fl)) { // At this point // awcTTF points to the FULL path to the font file. // If the font is in the system subdirectory we will just move it // to the fonts subdirectory. If the path in the registry is relative // we will leave it alone. If it is an absolute path, we shall // fix the registry entry to only contain relative path, the // absolute path is redundant. if (fl & (FONT_IN_SYSTEM_DIR | FONT_IN_FONTS_DIR)) { // find the bare file part, this is what will be written // in the registry pwcTTF = &awcTTF[wcslen(awcTTF) - 1]; while ((pwcTTF >= awcTTF) && (*pwcTTF != L'\\') && (*pwcTTF != L':')) pwcTTF--; pwcTTF++; if (fl & FONT_IN_SYSTEM_DIR) { // need to move the font to fonts dir, can reuse the // buffer on the stack to build the full destination path wcscpy(awcTmpBuf, gpwcFontsDir); lstrcatW(awcTmpBuf, L"\\"); lstrcatW(awcTmpBuf, pwcTTF); // note that MoveFile should succeed, for if there was // a font file of the same file name in %windir%\fonts dir // we would not have been in this code path. The only time // it could fail if the path in the registry is absolute. RIPMSG2(RIP_VERBOSE, "Moving %ws to %ws", awcTTF, awcTmpBuf); if (!gbWin31Upgrade) { UserVerify(MoveFileW(awcTTF, awcTmpBuf)); } else { // Boolean value TRUE means "do not copy if target exists" UserVerify(CopyFileW(awcTTF, awcTmpBuf, TRUE)); } } // check if the file path in the registry is absolute, // if so make it relative: if (!(fl & FONT_RELATIVE_PATH)) { RIPMSG2(RIP_VERBOSE, "writing to the registry:\n %ws=%ws", pwcValueName, pwcTTF); UserVerify(ERROR_SUCCESS == RegSetValueExW( hkey, // here is the key pwcValueName, 0, REG_SZ, (CONST BYTE*) pwcTTF, (DWORD)((wcslen(pwcTTF)+1) * sizeof(WCHAR)))); } } } } }
void xxxTrackMouseMove(PWND pwnd, int htEx, UINT message) { BOOL fNewpwndTrack; DWORD dwDTCancel = 0; TL tlpwnd; LPWSTR pstr; PDESKTOP pdesk = PtiCurrent()->rpdesk; PTHREADINFO ptiTrack; #if DBG /* * Let's warn if this function gets reenterd so we can make sure * nothing bad will follow. This should be a rare situation. * Look in gptiReEntered to find out who is already here. */ static UINT gcReEntered = 0; static PTHREADINFO gptiReEntered; if(gcReEntered++ != 0){ RIPMSG2(RIP_WARNING, "Reentered xxxTrackMouseMove; previous thread was %#p, current thread is %#p", gptiReEntered, PtiCurrent()); } gptiReEntered = PtiCurrent(); CheckLock(pwnd); /* * We must be on an interactive window station. */ if (pdesk->rpwinstaParent != NULL && pdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO) { RIPMSG0(RIP_ERROR, "Can't use tooltips on non-interactive winsta"); } { static POINT pt = {0, 0}; #ifdef UNDONE /* * We might have taken a guess on the hit test (see FindNCHitEx) * so if we're at the same point and same window, something * might be fishy */ if ((pt.x == gpsi->ptCursor.x) && (pt.y == gpsi->ptCursor.y) && (pdesk->spwndTrack == pwnd)) { RIPMSG1(RIP_WARNING, "xxxTrackMouseMove: Same point & window. %#p", pwnd); } #endif /* * Something is supposed to have changed or we're wasting time */ UserAssert((pt.x != gpsi->ptCursor.x) || (pt.y != gpsi->ptCursor.y) || (pdesk->spwndTrack != pwnd) || (pdesk->htEx != htEx) || (message != WM_MOUSEMOVE)); /* * Remember last tracked point */ pt = gpsi->ptCursor; } /* * pwnd is supposed to be on the current thread and queue */ UserAssert(PtiCurrent() == GETPTI(pwnd)); UserAssert(PtiCurrent()->pq == GETPTI(pwnd)->pq); #endif /* * Have we switched windows? */ fNewpwndTrack = (pdesk->spwndTrack != pwnd); /* * If no tracking is taking place, just go set the new * tracking state */ if (!(pdesk->dwDTFlags & DF_MOUSEMOVETRK)) { goto SetNewState; } /* * Potentially while we leave the critical section below in * xxxCancelMouseMoveTracking, spwndTrack could be destroyed and unlocked * and then we go and create the tooltip. This would mean that * DF_TOOLTIPACTIVE (part of DF_MOUSEMOVETRK test above) would be set, * but pdesk->spwndTrack would be NULL and we can AV dereferencing * pdesk->spwndTrack below. Prevent this by making the check here. */ if (pdesk->spwndTrack == NULL) { goto SetNewState; } /* * Nuke hottracking and deactivate tooltip state, if any. * Do it sychronously if we're tracking on the current queue; * Otherwise, post an event and let it happen later. */ ptiTrack = GETPTI(pdesk->spwndTrack); if (PtiCurrent()->pq == ptiTrack->pq) { dwDTCancel |= DF_HOTTRACKING; } else if (pdesk->dwDTFlags & (DF_HOTTRACKING | DF_TOOLTIPACTIVE)) { PostEventMessage(ptiTrack, ptiTrack->pq, QEVENT_CANCELMOUSEMOVETRK, pdesk->spwndTrack, pdesk->dwDTFlags, pdesk->htEx, DF_HOTTRACKING); /* * Paranoid assertion. If we're switching queues, we must * be switching windows. Did we just go through * ReattachThreads? */ UserAssert(pwnd != pdesk->spwndTrack); pdesk->dwDTFlags &= ~(DF_HOTTRACKING | DF_TOOLTIPACTIVE); } /* * If we're on the client area or the user clicked, * nuke the tooltip (if any). * Since we might want to re-show the tooltip, we don't nuke it * now if we swichted windows (we'll nuke it later if needed) */ if ((htEx == HTCLIENT) || (message != WM_MOUSEMOVE)) { dwDTCancel |= DF_TOOLTIPACTIVE; } /* * If we switched windows or crossed client/nonclinet boundaries, * end track mouse leave/hover. */ if (fNewpwndTrack || ((pdesk->htEx == HTCLIENT) ^ (htEx == HTCLIENT))) { dwDTCancel |= DF_TRACKMOUSEEVENT; } /* * Cancel whatever is active and needs to go away */ ThreadLockAlways(pdesk->spwndTrack, &tlpwnd); xxxCancelMouseMoveTracking(pdesk->dwDTFlags, pdesk->spwndTrack, pdesk->htEx, dwDTCancel); ThreadUnlock(&tlpwnd); pdesk->dwDTFlags &= ~dwDTCancel; SetNewState: /* * Hottracking/tooltip on mouse move if on NC hitest and enabled */ if ((htEx != HTCLIENT) && (message == WM_MOUSEMOVE) && TestEffectUP(HOTTRACKING)) { /* * Hottrack the new hit test area */ if (xxxHotTrack(pwnd, htEx, TRUE)) { pdesk->dwDTFlags |= DF_HOTTRACKING; } /* * Remove/set the tool tip. * We always do this synchronously because it doesn't mess * with pwnd's or spwnTrack's queue */ if ((pstr = IsTooltipHittest(pwnd, LOWORD(htEx))) != NULL) { PTOOLTIPWND pttwnd = (PTOOLTIPWND)pdesk->spwndTooltip; ThreadLockAlways(pttwnd, &tlpwnd); xxxCreateTooltip(pttwnd, pstr); ThreadUnlock(&tlpwnd); pdesk->dwDTFlags |= DF_TOOLTIP; } else { PTOOLTIPWND pttwnd = (PTOOLTIPWND)pdesk->spwndTooltip; ThreadLockAlways(pttwnd, &tlpwnd); xxxResetTooltip(pttwnd); ThreadUnlock(&tlpwnd); } } /* if (htEx != HTCLIENT) */ ValidateThreadLocks(NULL, PtiCurrent()->ptl, (ULONG_PTR)&pwnd, TRUE); /* * Update new track window if needed. */ if (fNewpwndTrack) { PWND pwndActivate; Lock(&pdesk->spwndTrack, pwnd); /* * Active window tracking. * If there is non-zero timeout, get the window we're supposed to activate * and set the timer. Otherwise, set the queue flag so * xxxActiveWindowTracking can do its thing. */ if ((message == WM_MOUSEMOVE) && TestUP(ACTIVEWINDOWTRACKING)) { if (UP(ACTIVEWNDTRKTIMEOUT) != 0) { pwndActivate = GetActiveTrackPwnd(pwnd, NULL); if (pwndActivate != NULL) { InternalSetTimer(pwndActivate, IDSYS_WNDTRACKING, UP(ACTIVEWNDTRKTIMEOUT), xxxSystemTimerProc, TMRF_SYSTEM); } } else { PtiCurrent()->pq->QF_flags |= QF_ACTIVEWNDTRACKING; } /* if (TestUP(ACTIVEWNDTRKZORDER)) */ } /* if (TestUP(ACTIVEWINDOWTRACKING)) */ } /* * Save new hit test code */ pdesk->htEx = htEx; #if DBG --gcReEntered; #endif }