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

srvinit.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 srvinit.c 00008 00009 Abstract: 00010 00011 This is the main initialization file for the console 00012 Server. 00013 00014 Author: 00015 00016 Therese Stowell (thereses) 11-Nov-1990 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "precomp.h" 00023 #pragma hdrstop 00024 00025 00026 CONST PCSR_API_ROUTINE ConsoleServerApiDispatchTable[ ConsolepMaxApiNumber - ConsolepOpenConsole ] = { 00027 (PCSR_API_ROUTINE)SrvOpenConsole, 00028 (PCSR_API_ROUTINE)SrvGetConsoleInput, 00029 (PCSR_API_ROUTINE)SrvWriteConsoleInput, 00030 (PCSR_API_ROUTINE)SrvReadConsoleOutput, 00031 (PCSR_API_ROUTINE)SrvWriteConsoleOutput, 00032 (PCSR_API_ROUTINE)SrvReadConsoleOutputString, 00033 (PCSR_API_ROUTINE)SrvWriteConsoleOutputString, 00034 (PCSR_API_ROUTINE)SrvFillConsoleOutput, 00035 (PCSR_API_ROUTINE)SrvGetConsoleMode, 00036 (PCSR_API_ROUTINE)SrvGetConsoleNumberOfFonts, 00037 (PCSR_API_ROUTINE)SrvGetConsoleNumberOfInputEvents, 00038 (PCSR_API_ROUTINE)SrvGetConsoleScreenBufferInfo, 00039 (PCSR_API_ROUTINE)SrvGetConsoleCursorInfo, 00040 (PCSR_API_ROUTINE)SrvGetConsoleMouseInfo, 00041 (PCSR_API_ROUTINE)SrvGetConsoleFontInfo, 00042 (PCSR_API_ROUTINE)SrvGetConsoleFontSize, 00043 (PCSR_API_ROUTINE)SrvGetConsoleCurrentFont, 00044 (PCSR_API_ROUTINE)SrvSetConsoleMode, 00045 (PCSR_API_ROUTINE)SrvSetConsoleActiveScreenBuffer, 00046 (PCSR_API_ROUTINE)SrvFlushConsoleInputBuffer, 00047 (PCSR_API_ROUTINE)SrvGetLargestConsoleWindowSize, 00048 (PCSR_API_ROUTINE)SrvSetConsoleScreenBufferSize, 00049 (PCSR_API_ROUTINE)SrvSetConsoleCursorPosition, 00050 (PCSR_API_ROUTINE)SrvSetConsoleCursorInfo, 00051 (PCSR_API_ROUTINE)SrvSetConsoleWindowInfo, 00052 (PCSR_API_ROUTINE)SrvScrollConsoleScreenBuffer, 00053 (PCSR_API_ROUTINE)SrvSetConsoleTextAttribute, 00054 (PCSR_API_ROUTINE)SrvSetConsoleFont, 00055 (PCSR_API_ROUTINE)SrvSetConsoleIcon, 00056 (PCSR_API_ROUTINE)SrvReadConsole, 00057 (PCSR_API_ROUTINE)SrvWriteConsole, 00058 (PCSR_API_ROUTINE)SrvDuplicateHandle, 00059 (PCSR_API_ROUTINE)SrvGetHandleInformation, 00060 (PCSR_API_ROUTINE)SrvSetHandleInformation, 00061 (PCSR_API_ROUTINE)SrvCloseHandle, 00062 (PCSR_API_ROUTINE)SrvVerifyConsoleIoHandle, 00063 (PCSR_API_ROUTINE)SrvAllocConsole, 00064 (PCSR_API_ROUTINE)SrvFreeConsole, 00065 (PCSR_API_ROUTINE)SrvGetConsoleTitle, 00066 (PCSR_API_ROUTINE)SrvSetConsoleTitle, 00067 (PCSR_API_ROUTINE)SrvCreateConsoleScreenBuffer, 00068 (PCSR_API_ROUTINE)SrvInvalidateBitMapRect, 00069 (PCSR_API_ROUTINE)SrvVDMConsoleOperation, 00070 (PCSR_API_ROUTINE)SrvSetConsoleCursor, 00071 (PCSR_API_ROUTINE)SrvShowConsoleCursor, 00072 (PCSR_API_ROUTINE)SrvConsoleMenuControl, 00073 (PCSR_API_ROUTINE)SrvSetConsolePalette, 00074 (PCSR_API_ROUTINE)SrvSetConsoleDisplayMode, 00075 (PCSR_API_ROUTINE)SrvRegisterConsoleVDM, 00076 (PCSR_API_ROUTINE)SrvGetConsoleHardwareState, 00077 (PCSR_API_ROUTINE)SrvSetConsoleHardwareState, 00078 (PCSR_API_ROUTINE)SrvGetConsoleDisplayMode, 00079 (PCSR_API_ROUTINE)SrvAddConsoleAlias, 00080 (PCSR_API_ROUTINE)SrvGetConsoleAlias, 00081 (PCSR_API_ROUTINE)SrvGetConsoleAliasesLength, 00082 (PCSR_API_ROUTINE)SrvGetConsoleAliasExesLength, 00083 (PCSR_API_ROUTINE)SrvGetConsoleAliases, 00084 (PCSR_API_ROUTINE)SrvGetConsoleAliasExes, 00085 (PCSR_API_ROUTINE)SrvExpungeConsoleCommandHistory, 00086 (PCSR_API_ROUTINE)SrvSetConsoleNumberOfCommands, 00087 (PCSR_API_ROUTINE)SrvGetConsoleCommandHistoryLength, 00088 (PCSR_API_ROUTINE)SrvGetConsoleCommandHistory, 00089 (PCSR_API_ROUTINE)SrvSetConsoleCommandHistoryMode, 00090 (PCSR_API_ROUTINE)SrvGetConsoleCP, 00091 (PCSR_API_ROUTINE)SrvSetConsoleCP, 00092 (PCSR_API_ROUTINE)SrvSetConsoleKeyShortcuts, 00093 (PCSR_API_ROUTINE)SrvSetConsoleMenuClose, 00094 (PCSR_API_ROUTINE)SrvConsoleNotifyLastClose, 00095 (PCSR_API_ROUTINE)SrvGenerateConsoleCtrlEvent, 00096 (PCSR_API_ROUTINE)SrvGetConsoleKeyboardLayoutName, 00097 (PCSR_API_ROUTINE)SrvGetConsoleWindow, 00098 #if defined(FE_SB) 00099 (PCSR_API_ROUTINE)SrvGetConsoleCharType, 00100 (PCSR_API_ROUTINE)SrvSetConsoleLocalEUDC, 00101 (PCSR_API_ROUTINE)SrvSetConsoleCursorMode, 00102 (PCSR_API_ROUTINE)SrvGetConsoleCursorMode, 00103 (PCSR_API_ROUTINE)SrvRegisterConsoleOS2, 00104 (PCSR_API_ROUTINE)SrvSetConsoleOS2OemFormat, 00105 #if defined(FE_IME) 00106 (PCSR_API_ROUTINE)SrvGetConsoleNlsMode, 00107 (PCSR_API_ROUTINE)SrvSetConsoleNlsMode, 00108 (PCSR_API_ROUTINE)SrvRegisterConsoleIME, 00109 (PCSR_API_ROUTINE)SrvUnregisterConsoleIME, 00110 #endif // FE_IME 00111 #endif // FE_SB 00112 (PCSR_API_ROUTINE)SrvGetConsoleLangId 00113 }; 00114 00115 CONST BOOLEAN ConsoleServerApiServerValidTable[ ConsolepMaxApiNumber - ConsolepOpenConsole ] = { 00116 FALSE, // OpenConsole 00117 FALSE, // GetConsoleInput, 00118 FALSE, // WriteConsoleInput, 00119 FALSE, // ReadConsoleOutput, 00120 FALSE, // WriteConsoleOutput, 00121 FALSE, // ReadConsoleOutputString, 00122 FALSE, // WriteConsoleOutputString, 00123 FALSE, // FillConsoleOutput, 00124 FALSE, // GetConsoleMode, 00125 FALSE, // GetNumberOfConsoleFonts, 00126 FALSE, // GetNumberOfConsoleInputEvents, 00127 FALSE, // GetConsoleScreenBufferInfo, 00128 FALSE, // GetConsoleCursorInfo, 00129 FALSE, // GetConsoleMouseInfo, 00130 FALSE, // GetConsoleFontInfo, 00131 FALSE, // GetConsoleFontSize, 00132 FALSE, // GetCurrentConsoleFont, 00133 FALSE, // SetConsoleMode, 00134 FALSE, // SetConsoleActiveScreenBuffer, 00135 FALSE, // FlushConsoleInputBuffer, 00136 FALSE, // GetLargestConsoleWindowSize, 00137 FALSE, // SetConsoleScreenBufferSize, 00138 FALSE, // SetConsoleCursorPosition, 00139 FALSE, // SetConsoleCursorInfo, 00140 FALSE, // SetConsoleWindowInfo, 00141 FALSE, // ScrollConsoleScreenBuffer, 00142 FALSE, // SetConsoleTextAttribute, 00143 FALSE, // SetConsoleFont, 00144 FALSE, // SetConsoleIcon 00145 FALSE, // ReadConsole, 00146 FALSE, // WriteConsole, 00147 FALSE, // DuplicateHandle, 00148 FALSE, // GetHandleInformation, 00149 FALSE, // SetHandleInformation, 00150 FALSE, // CloseHandle 00151 FALSE, // VerifyConsoleIoHandle 00152 FALSE, // AllocConsole, 00153 FALSE, // FreeConsole 00154 FALSE, // GetConsoleTitle, 00155 FALSE, // SetConsoleTitle, 00156 FALSE, // CreateConsoleScreenBuffer 00157 FALSE, // InvalidateConsoleBitmapRect 00158 FALSE, // VDMConsoleOperation 00159 FALSE, // SetConsoleCursor, 00160 FALSE, // ShowConsoleCursor 00161 FALSE, // ConsoleMenuControl 00162 FALSE, // SetConsolePalette 00163 FALSE, // SetConsoleDisplayMode 00164 FALSE, // RegisterConsoleVDM, 00165 FALSE, // GetConsoleHardwareState 00166 FALSE, // SetConsoleHardwareState 00167 TRUE, // GetConsoleDisplayMode 00168 FALSE, // AddConsoleAlias, 00169 FALSE, // GetConsoleAlias, 00170 FALSE, // GetConsoleAliasesLength, 00171 FALSE, // GetConsoleAliasExesLength, 00172 FALSE, // GetConsoleAliases, 00173 FALSE, // GetConsoleAliasExes 00174 FALSE, // ExpungeConsoleCommandHistory, 00175 FALSE, // SetConsoleNumberOfCommands, 00176 FALSE, // GetConsoleCommandHistoryLength, 00177 FALSE, // GetConsoleCommandHistory, 00178 FALSE, // SetConsoleCommandHistoryMode 00179 FALSE, // SrvGetConsoleCP, 00180 FALSE, // SrvSetConsoleCP, 00181 FALSE, // SrvSetConsoleKeyShortcuts, 00182 FALSE, // SrvSetConsoleMenuClose 00183 FALSE, // SrvConsoleNotifyLastClose 00184 FALSE, // SrvGenerateConsoleCtrlEvent 00185 FALSE, // SrvGetConsoleKeyboardLayoutName 00186 FALSE, // SrvGetConsoleWindow, 00187 #if defined(FE_SB) 00188 FALSE, // GetConsoleCharType 00189 FALSE, // SrvSetConsoleLocalEUDC, 00190 FALSE, // SrvSetConsoleCursorMode, 00191 FALSE, // SrvGetConsoleCursorMode 00192 FALSE, // SrvRegisterConsoleOS2, 00193 FALSE, // SrvSetConsoleOS2OemFormat, 00194 #if defined(FE_IME) 00195 FALSE, // GetConsoleNlsMode 00196 FALSE, // SetConsoleNlsMode 00197 FALSE, // RegisterConsoleIME 00198 FALSE, // UnregisterConsoleIME 00199 #endif // FE_IME 00200 #endif // FE_SB 00201 FALSE // GetConsoleLangId 00202 }; 00203 00204 #if DBG 00205 PSZ ConsoleServerApiNameTable[ ConsolepMaxApiNumber - ConsolepOpenConsole ] = { 00206 "SrvOpenConsole", 00207 "SrvGetConsoleInput", 00208 "SrvWriteConsoleInput", 00209 "SrvReadConsoleOutput", 00210 "SrvWriteConsoleOutput", 00211 "SrvReadConsoleOutputString", 00212 "SrvWriteConsoleOutputString", 00213 "SrvFillConsoleOutput", 00214 "SrvGetConsoleMode", 00215 "SrvGetConsoleNumberOfFonts", 00216 "SrvGetConsoleNumberOfInputEvents", 00217 "SrvGetConsoleScreenBufferInfo", 00218 "SrvGetConsoleCursorInfo", 00219 "SrvGetConsoleMouseInfo", 00220 "SrvGetConsoleFontInfo", 00221 "SrvGetConsoleFontSize", 00222 "SrvGetConsoleCurrentFont", 00223 "SrvSetConsoleMode", 00224 "SrvSetConsoleActiveScreenBuffer", 00225 "SrvFlushConsoleInputBuffer", 00226 "SrvGetLargestConsoleWindowSize", 00227 "SrvSetConsoleScreenBufferSize", 00228 "SrvSetConsoleCursorPosition", 00229 "SrvSetConsoleCursorInfo", 00230 "SrvSetConsoleWindowInfo", 00231 "SrvScrollConsoleScreenBuffer", 00232 "SrvSetConsoleTextAttribute", 00233 "SrvSetConsoleFont", 00234 "SrvSetConsoleIcon", 00235 "SrvReadConsole", 00236 "SrvWriteConsole", 00237 "SrvDuplicateHandle", 00238 "SrvGetHandleInformation", 00239 "SrvSetHandleInformation", 00240 "SrvCloseHandle", 00241 "SrvVerifyConsoleIoHandle", 00242 "SrvAllocConsole", 00243 "SrvFreeConsole", 00244 "SrvGetConsoleTitle", 00245 "SrvSetConsoleTitle", 00246 "SrvCreateConsoleScreenBuffer", 00247 "SrvInvalidateBitMapRect", 00248 "SrvVDMConsoleOperation", 00249 "SrvSetConsoleCursor", 00250 "SrvShowConsoleCursor", 00251 "SrvConsoleMenuControl", 00252 "SrvSetConsolePalette", 00253 "SrvSetConsoleDisplayMode", 00254 "SrvRegisterConsoleVDM", 00255 "SrvGetConsoleHardwareState", 00256 "SrvSetConsoleHardwareState", 00257 "SrvGetConsoleDisplayMode", 00258 "SrvAddConsoleAlias", 00259 "SrvGetConsoleAlias", 00260 "SrvGetConsoleAliasesLength", 00261 "SrvGetConsoleAliasExesLength", 00262 "SrvGetConsoleAliases", 00263 "SrvGetConsoleAliasExes", 00264 "SrvExpungeConsoleCommandHistory", 00265 "SrvSetConsoleNumberOfCommands", 00266 "SrvGetConsoleCommandHistoryLength", 00267 "SrvGetConsoleCommandHistory", 00268 "SrvSetConsoleCommandHistoryMode", 00269 "SrvGetConsoleCP", 00270 "SrvSetConsoleCP", 00271 "SrvSetConsoleKeyShortcuts", 00272 "SrvSetConsoleMenuClose", 00273 "SrvConsoleNotifyLastClose", 00274 "SrvGenerateConsoleCtrlEvent", 00275 "SrvGetConsoleKeyboardLayoutName", 00276 "SrvGetConsoleWindow", 00277 #if defined(FE_SB) 00278 "SrvGetConsoleCharType", 00279 "SrvSetConsoleLocalEUDC", 00280 "SrvSetConsoleCursorMode", 00281 "SrvGetConsoleCursorMode", 00282 "SrvRegisterConsoleOS2", 00283 "SrvSetConsoleOS2OemFormat", 00284 #if defined(FE_IME) 00285 "SrvGetConsoleNlsMode", 00286 "SrvSetConsoleNlsMode", 00287 "SrvRegisterConsoleIME", 00288 "SrvUnregisterConsoleIME", 00289 #endif // FE_IME 00290 #endif // FE_SB 00291 "SrvGetConsoleLangId" 00292 }; 00293 #endif // DBG 00294 00295 BOOL FullScreenInitialized; 00296 CRITICAL_SECTION ConsoleVDMCriticalSection; 00297 PCONSOLE_INFORMATION ConsoleVDMOnSwitching; 00298 00299 00300 CRITICAL_SECTION ConsoleInitWindowsLock; 00301 BOOL fOneTimeInitialized; 00302 00303 UINT OEMCP; 00304 UINT WINDOWSCP; 00305 UINT ConsoleOutputCP; 00306 CONSOLE_REGISTRY_INFO DefaultRegInfo; 00307 #if defined(FE_SB) 00308 BOOLEAN gfIsDBCSACP; 00309 #endif 00310 00311 VOID 00312 UnregisterVDM( 00313 IN PCONSOLE_INFORMATION Console 00314 ); 00315 00316 ULONG 00317 NonConsoleProcessShutdown( 00318 PCSR_PROCESS Process, 00319 DWORD dwFlags 00320 ); 00321 00322 ULONG 00323 ConsoleClientShutdown( 00324 PCSR_PROCESS Process, 00325 ULONG Flags, 00326 BOOLEAN fFirstPass 00327 ); 00328 00329 NTSTATUS 00330 ConsoleClientConnectRoutine( 00331 IN PCSR_PROCESS Process, 00332 IN OUT PVOID ConnectionInfo, 00333 IN OUT PULONG ConnectionInfoLength 00334 ); 00335 00336 VOID 00337 ConsoleClientDisconnectRoutine( 00338 IN PCSR_PROCESS Process 00339 ); 00340 00341 VOID ConsolePlaySound( 00342 VOID 00343 ); 00344 00345 00346 00347 HANDLE ghInstance; 00348 HICON ghDefaultIcon; 00349 HICON ghDefaultSmIcon; 00350 HCURSOR ghNormalCursor; 00351 00352 PWIN32HEAP pConHeap; 00353 DWORD dwConBaseTag; 00354 00355 DWORD gExtendedEditKey; 00356 BOOL gfTrimLeadingZeros; 00357 00358 BOOL gfLoadConIme; 00359 00360 VOID LoadLinkInfo( 00361 PCONSOLE_INFO ConsoleInfo, 00362 LPWSTR Title, 00363 LPDWORD TitleLength, 00364 LPWSTR CurDir, 00365 LPWSTR AppName 00366 ) 00367 { 00368 DWORD dwLinkLen; 00369 WCHAR LinkName[ MAX_PATH+1 ]; 00370 LNKPROPNTCONSOLE linkprops; 00371 LPWSTR pszIconLocation; 00372 int nIconIndex; 00373 00374 ConsoleInfo->uCodePage = OEMCP; 00375 00376 // Do some initialization 00377 ConsoleInfo->hIcon = ghDefaultIcon; 00378 ConsoleInfo->hSmIcon = ghDefaultSmIcon; 00379 pszIconLocation = NULL; 00380 nIconIndex = 0; 00381 00382 // Try to impersonate the client-side thread 00383 if (!CsrImpersonateClient(NULL)) { 00384 ConsoleInfo->dwStartupFlags &= (~STARTF_TITLEISLINKNAME); 00385 goto DefaultInit; 00386 } 00387 00388 // Did we get started from a link? 00389 if (ConsoleInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) { 00390 00391 DWORD Success; 00392 DWORD oldLen; 00393 00394 // Get the filename of the link (TitleLength is BYTES, not CHARS) 00395 dwLinkLen = (DWORD)(min(*TitleLength,(MAX_PATH+1)*sizeof(WCHAR))); 00396 RtlCopyMemory(LinkName,Title,dwLinkLen); 00397 LinkName[ MAX_PATH ] = (WCHAR)0; 00398 00399 00400 // Get the title for the window, which is effectively the link file name 00401 oldLen = *TitleLength; 00402 *TitleLength = GetTitleFromLinkName( LinkName, Title ); 00403 if (*TitleLength < oldLen) 00404 Title[ *TitleLength / sizeof(WCHAR) ] = L'\0'; 00405 00406 // try to get console properties from the link 00407 Success = GetLinkProperties( LinkName, 00408 &linkprops, 00409 sizeof(linkprops) 00410 ); 00411 00412 if (Success == LINK_NOINFO) { 00413 ConsoleInfo->dwStartupFlags &= (~STARTF_TITLEISLINKNAME); 00414 goto NormalInit; 00415 } 00416 00417 if (linkprops.pszIconLocation && *linkprops.pszIconLocation) { 00418 pszIconLocation = linkprops.pszIconLocation; 00419 nIconIndex = linkprops.uIcon; 00420 ConsoleInfo->iIconId = 0; 00421 } 00422 00423 // Transfer link settings 00424 ConsoleInfo->dwHotKey = linkprops.uHotKey; 00425 ConsoleInfo->wShowWindow = (WORD)linkprops.uShowCmd; 00426 00427 if (Success == LINK_SIMPLEINFO) { 00428 ConsoleInfo->dwStartupFlags &= (~STARTF_TITLEISLINKNAME); 00429 goto NormalInit; 00430 } 00431 00432 // Transfer console link settings 00433 ConsoleInfo->wFillAttribute = linkprops.console_props.wFillAttribute; 00434 ConsoleInfo->wPopupFillAttribute = linkprops.console_props.wPopupFillAttribute; 00435 00436 RtlCopyMemory( &ConsoleInfo->dwScreenBufferSize, 00437 &linkprops.console_props.dwScreenBufferSize, 00438 sizeof(NT_CONSOLE_PROPS) - FIELD_OFFSET(NT_CONSOLE_PROPS, dwScreenBufferSize) 00439 ); 00440 00441 ConsoleInfo->uCodePage = linkprops.fe_console_props.uCodePage; 00442 00443 #if 0 00444 { 00445 00446 INT i; 00447 00448 DbgPrint("[LoadLinkInfo Properties for %ws]\n", Title ); 00449 DbgPrint(" wFillAttribute = 0x%04X\n", ConsoleInfo->wFillAttribute ); 00450 DbgPrint(" wPopupFillAttribute = 0x%04X\n", ConsoleInfo->wPopupFillAttribute ); 00451 DbgPrint(" dwScreenBufferSize = (%d , %d)\n", ConsoleInfo->dwScreenBufferSize.X, ConsoleInfo->dwScreenBufferSize.Y ); 00452 DbgPrint(" dwWindowSize = (%d , %d)\n", ConsoleInfo->dwWindowSize.X, ConsoleInfo->dwWindowSize.Y ); 00453 DbgPrint(" dwWindowOrigin = (%d , %d)\n", ConsoleInfo->dwWindowOrigin.X, ConsoleInfo->dwWindowOrigin.Y ); 00454 DbgPrint(" nFont = 0x%X\n", ConsoleInfo->nFont ); 00455 DbgPrint(" nInputBufferSize = 0x%X\n", ConsoleInfo->nInputBufferSize ); 00456 DbgPrint(" dwFontSize = (%d , %d)\n", ConsoleInfo->dwFontSize.X, ConsoleInfo->dwFontSize.Y ); 00457 DbgPrint(" uFontFamily = 0x%08X\n", ConsoleInfo->uFontFamily ); 00458 DbgPrint(" uFontWeight = 0x%08X\n", ConsoleInfo->uFontWeight ); 00459 DbgPrint(" FaceName = %ws\n", ConsoleInfo->FaceName ); 00460 DbgPrint(" uCursorSize = %d\n", ConsoleInfo->uCursorSize ); 00461 DbgPrint(" bFullScreen = %s\n", ConsoleInfo->bFullScreen ? "TRUE" : "FALSE" ); 00462 DbgPrint(" bQuickEdit = %s\n", ConsoleInfo->bQuickEdit ? "TRUE" : "FALSE" ); 00463 DbgPrint(" bInsertMode = %s\n", ConsoleInfo->bInsertMode ? "TRUE" : "FALSE" ); 00464 DbgPrint(" bAutoPosition = %s\n", ConsoleInfo->bAutoPosition ? "TRUE" : "FALSE" ); 00465 DbgPrint(" uHistoryBufferSize = %d\n", ConsoleInfo->uHistoryBufferSize ); 00466 DbgPrint(" uNumHistoryBuffers = %d\n", ConsoleInfo->uNumberOfHistoryBuffers ); 00467 DbgPrint(" bHistoryNoDup = %s\n", ConsoleInfo->bHistoryNoDup ? "TRUE" : "FALSE" ); 00468 DbgPrint(" ColorTable = [" ); 00469 i=0; 00470 while( i < 16 ) 00471 { 00472 DbgPrint("\n "); 00473 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00474 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00475 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00476 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00477 } 00478 DbgPrint( "]\n\n" ); 00479 } 00480 #endif 00481 00482 ConsoleInfo->dwStartupFlags &= ~(STARTF_USESIZE | STARTF_USECOUNTCHARS); 00483 } 00484 00485 NormalInit: 00486 00487 // 00488 // Go get the icon 00489 // 00490 00491 if (pszIconLocation == NULL) { 00492 dwLinkLen = RtlDosSearchPath_U(CurDir, 00493 AppName, 00494 NULL, 00495 sizeof(LinkName), 00496 LinkName, 00497 NULL); 00498 if (dwLinkLen > 0 && dwLinkLen < sizeof(LinkName)) { 00499 pszIconLocation = LinkName; 00500 } else { 00501 pszIconLocation = AppName; 00502 } 00503 } 00504 00505 if (pszIconLocation != NULL) { 00506 HICON hIcon, hSmIcon; 00507 hIcon = hSmIcon = NULL; 00508 PrivateExtractIconExW(pszIconLocation, 00509 nIconIndex, 00510 &hIcon, 00511 &hSmIcon, 00512 1); 00513 /* 00514 * If there is no large icon, use the default ones 00515 * If there is only a large icon in the resource, do not use 00516 * the default small one but let it be NULL so we'll stretch the large one 00517 */ 00518 if (hIcon != NULL) { 00519 ConsoleInfo->hIcon = hIcon; 00520 ConsoleInfo->hSmIcon = hSmIcon; 00521 } 00522 } 00523 00524 CsrRevertToSelf(); 00525 00526 if (! IsValidCodePage(ConsoleInfo->uCodePage)) { // fail safe 00527 ConsoleInfo->uCodePage = OEMCP; 00528 } 00529 00530 if (!(ConsoleInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)) { 00531 CONSOLE_REGISTRY_INFO RegInfo; 00532 00533 DefaultInit: 00534 // 00535 // read values from the registry 00536 // 00537 00538 RegInfo = DefaultRegInfo; 00539 GetRegistryValues(Title, &RegInfo); 00540 00541 // 00542 // if a value isn't specified in STARTUPINFO, then use the one 00543 // from the registry. 00544 // 00545 00546 if (!(ConsoleInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)) { 00547 ConsoleInfo->wFillAttribute = RegInfo.ScreenFill.Attributes; 00548 } 00549 ConsoleInfo->wPopupFillAttribute = RegInfo.PopupFill.Attributes; 00550 00551 if (!(ConsoleInfo->dwStartupFlags & STARTF_USECOUNTCHARS)) { 00552 ConsoleInfo->dwScreenBufferSize = RegInfo.ScreenBufferSize; 00553 } 00554 if (!(ConsoleInfo->dwStartupFlags & STARTF_USESIZE)) { 00555 ConsoleInfo->dwWindowSize = RegInfo.WindowSize; 00556 } 00557 if (!(ConsoleInfo->dwStartupFlags & STARTF_USEPOSITION)) { 00558 ConsoleInfo->dwWindowOrigin = RegInfo.WindowOrigin; 00559 ConsoleInfo->bAutoPosition = RegInfo.AutoPosition; 00560 } else { 00561 ConsoleInfo->bAutoPosition = FALSE; 00562 } 00563 if (!(ConsoleInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)) { 00564 ConsoleInfo->bFullScreen = RegInfo.FullScreen; 00565 } else { 00566 ConsoleInfo->bFullScreen = TRUE; 00567 } 00568 00569 ConsoleInfo->uFontFamily = RegInfo.FontFamily; 00570 ConsoleInfo->uFontWeight = RegInfo.FontWeight; 00571 ConsoleInfo->dwFontSize = RegInfo.FontSize; 00572 RtlCopyMemory(ConsoleInfo->FaceName, RegInfo.FaceName, sizeof(RegInfo.FaceName)); 00573 00574 ConsoleInfo->bQuickEdit = RegInfo.QuickEdit; 00575 ConsoleInfo->bInsertMode = RegInfo.InsertMode; 00576 00577 ConsoleInfo->uCursorSize = RegInfo.CursorSize; 00578 ConsoleInfo->uHistoryBufferSize = RegInfo.HistoryBufferSize; 00579 ConsoleInfo->uNumberOfHistoryBuffers = RegInfo.NumberOfHistoryBuffers; 00580 ConsoleInfo->bHistoryNoDup = RegInfo.HistoryNoDup; 00581 RtlCopyMemory(ConsoleInfo->ColorTable, RegInfo.ColorTable, sizeof(RegInfo.ColorTable)); 00582 #ifdef FE_SB 00583 ConsoleInfo->uCodePage = RegInfo.CodePage; 00584 #endif 00585 } 00586 } 00587 00588 00589 BOOL 00590 InitWindowClass( VOID ) 00591 { 00592 WNDCLASSEX wc; 00593 BOOL retval; 00594 ATOM atomConsoleClass; 00595 00596 ghNormalCursor = LoadCursor(NULL, IDC_ARROW); 00597 ASSERT(ghModuleWin != NULL); 00598 ghDefaultIcon = LoadIcon(ghModuleWin, MAKEINTRESOURCE(IDI_CONSOLE)); 00599 ghDefaultSmIcon = LoadImage(ghModuleWin, MAKEINTRESOURCE(IDI_CONSOLE), IMAGE_ICON, 00600 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 00601 LR_SHARED); 00602 wc.hIcon = ghDefaultIcon; 00603 wc.cbSize = sizeof(WNDCLASSEX); 00604 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; 00605 wc.lpfnWndProc = ConsoleWindowProc; 00606 wc.cbClsExtra = 0; 00607 wc.cbWndExtra = GWL_CONSOLE_WNDALLOC; 00608 wc.hInstance = ghInstance; 00609 wc.hCursor = ghNormalCursor; 00610 wc.hbrBackground = CreateSolidBrush(DefaultRegInfo.ColorTable[LOBYTE(DefaultRegInfo.ScreenFill.Attributes >> 4) & 0xF]); 00611 wc.lpszMenuName = NULL; 00612 wc.lpszClassName = CONSOLE_WINDOW_CLASS; 00613 wc.hIconSm = ghDefaultSmIcon; 00614 00615 atomConsoleClass = RegisterClassEx(&wc); 00616 retval = (atomConsoleClass != 0); 00617 00618 if (retval) 00619 NtUserConsoleControl(ConsoleClassAtom, &atomConsoleClass, sizeof(ATOM)); 00620 00621 return retval; 00622 } 00623 00624 00625 NTSTATUS 00626 InitWindowsStuff( 00627 HDESK hdesk, 00628 LPDWORD lpdwThreadId) 00629 { 00630 NTSTATUS Status = STATUS_SUCCESS; 00631 CLIENT_ID ClientId; 00632 CONSOLEDESKTOPCONSOLETHREAD ConsoleDesktopInfo; 00633 INPUT_THREAD_INIT_INFO InputThreadInitInfo; 00634 00635 // 00636 // This routine must be done within a critical section to ensure that 00637 // only one thread can initialize at a time. We need a special critical 00638 // section here because Csr calls into ConsoleAddProcessRoutine with 00639 // it's own critical section locked and then tries to grab the 00640 // ConsoleHandleTableLock. If we call CsrAddStaticServerThread here 00641 // with the ConsoleHandleTableLock locked we could get into a deadlock 00642 // situation. This critical section should not be used anywhere else. 00643 // 00644 00645 RtlEnterCriticalSection(&ConsoleInitWindowsLock); 00646 00647 ConsoleDesktopInfo.hdesk = hdesk; 00648 ConsoleDesktopInfo.dwThreadId = (DWORD)-1; 00649 NtUserConsoleControl(ConsoleDesktopConsoleThread, &ConsoleDesktopInfo, 00650 sizeof(ConsoleDesktopInfo)); 00651 if (ConsoleDesktopInfo.dwThreadId == 0) { 00652 00653 if (!fOneTimeInitialized) { 00654 00655 #if defined(FE_SB) 00656 InitializeDbcsMisc(); 00657 #endif 00658 00659 FullScreenInitialized = InitializeFullScreen(); 00660 00661 // 00662 // read the registry values 00663 // 00664 00665 GetRegistryValues(L"", &DefaultRegInfo); 00666 00667 // 00668 // allocate buffer for scrolling 00669 // 00670 00671 Status = InitializeScrollBuffer(); 00672 ASSERT (NT_SUCCESS(Status)); 00673 if (!NT_SUCCESS(Status)) 00674 goto ErrorExit; 00675 } 00676 00677 // 00678 // create GetMessage thread 00679 // 00680 00681 Status = NtCreateEvent(&InputThreadInitInfo.InitCompleteEventHandle, EVENT_ALL_ACCESS, 00682 NULL, NotificationEvent, FALSE); 00683 if (!NT_SUCCESS(Status)) { 00684 goto ErrorExit; 00685 } 00686 00687 Status = NtDuplicateObject(NtCurrentProcess(), hdesk, 00688 NtCurrentProcess(), &InputThreadInitInfo.DesktopHandle, 0, 00689 0, DUPLICATE_SAME_ACCESS); 00690 if (!NT_SUCCESS(Status)) { 00691 NtClose(InputThreadInitInfo.InitCompleteEventHandle); 00692 goto ErrorExit; 00693 } 00694 00695 // can't call CreateThread from server 00696 Status = RtlCreateUserThread(NtCurrentProcess(), 00697 (PSECURITY_DESCRIPTOR) NULL, 00698 TRUE, 00699 0, 00700 0, 00701 0, 00702 (PUSER_THREAD_START_ROUTINE)ConsoleInputThread, 00703 &InputThreadInitInfo, 00704 &InputThreadInitInfo.ThreadHandle, 00705 &ClientId 00706 ); 00707 if (!NT_SUCCESS(Status)) { 00708 NtClose(InputThreadInitInfo.InitCompleteEventHandle); 00709 CloseDesktop(InputThreadInitInfo.DesktopHandle); 00710 goto ErrorExit; 00711 } 00712 00713 CsrAddStaticServerThread(InputThreadInitInfo.ThreadHandle,&ClientId,0); 00714 NtResumeThread(InputThreadInitInfo.ThreadHandle, NULL); 00715 NtWaitForSingleObject(InputThreadInitInfo.InitCompleteEventHandle, FALSE, NULL); 00716 NtClose(InputThreadInitInfo.InitCompleteEventHandle); 00717 00718 if (!NT_SUCCESS(InputThreadInitInfo.InitStatus)) { 00719 goto ErrorExit; 00720 } 00721 00722 *lpdwThreadId = HandleToUlong(ClientId.UniqueThread); 00723 00724 fOneTimeInitialized=TRUE; 00725 } else { 00726 *lpdwThreadId = ConsoleDesktopInfo.dwThreadId; 00727 } 00728 00729 ErrorExit: 00730 RtlLeaveCriticalSection(&ConsoleInitWindowsLock); 00731 00732 return Status; 00733 } 00734 00735 00736 NTSTATUS APIPRIVATE 00737 ConServerDllInitialization( 00738 PCSR_SERVER_DLL LoadedServerDll 00739 ) 00740 00741 /*++ 00742 00743 Routine Description: 00744 00745 This routine is called to initialize the server dll. It initializes 00746 the console handle table. 00747 00748 Arguments: 00749 00750 LoadedServerDll - Pointer to console server dll data 00751 00752 Return Value: 00753 00754 --*/ 00755 00756 { 00757 NTSTATUS Status; 00758 00759 LoadedServerDll->ApiNumberBase = CONSRV_FIRST_API_NUMBER; 00760 LoadedServerDll->MaxApiNumber = ConsolepMaxApiNumber; 00761 LoadedServerDll->ApiDispatchTable = (PCSR_API_ROUTINE *)ConsoleServerApiDispatchTable; 00762 LoadedServerDll->ApiServerValidTable = (PBOOLEAN)ConsoleServerApiServerValidTable; 00763 #if DBG 00764 LoadedServerDll->ApiNameTable = ConsoleServerApiNameTable; 00765 #else 00766 LoadedServerDll->ApiNameTable = NULL; 00767 #endif 00768 LoadedServerDll->PerProcessDataLength = sizeof(CONSOLE_PER_PROCESS_DATA); 00769 LoadedServerDll->ConnectRoutine = ConsoleClientConnectRoutine; 00770 LoadedServerDll->DisconnectRoutine = ConsoleClientDisconnectRoutine; 00771 LoadedServerDll->AddProcessRoutine = ConsoleAddProcessRoutine; 00772 LoadedServerDll->ShutdownProcessRoutine = ConsoleClientShutdown; 00773 00774 ghInstance = LoadedServerDll->ModuleHandle; 00775 00776 // initialize data structures 00777 00778 InitWin32HeapStubs(); 00779 00780 pConHeap = Win32HeapCreate( 00781 "CH_Head", 00782 "CH_Tail", 00783 HEAP_GROWABLE | HEAP_CLASS_5 | 00784 #if DBG 00785 HEAP_TAIL_CHECKING_ENABLED, 00786 #else 00787 0, 00788 #endif 00789 NULL, // HeapBase 00790 64 * 1024, // ReserveSize 00791 4096, // CommitSize 00792 NULL, // Lock to use for serialization 00793 NULL); // GrowthThreshold 00794 00795 // pConHeap = RtlProcessHeap(); 00796 00797 if (pConHeap == NULL) { 00798 return STATUS_NO_MEMORY; 00799 } 00800 00801 dwConBaseTag = Win32HeapCreateTag( pConHeap, 00802 0, 00803 L"CON!", 00804 L"TMP\0" 00805 L"BMP\0" 00806 L"ALIAS\0" 00807 L"HISTORY\0" 00808 L"TITLE\0" 00809 L"HANDLE\0" 00810 L"CONSOLE\0" 00811 L"ICON\0" 00812 L"BUFFER\0" 00813 L"WAIT\0" 00814 L"FONT\0" 00815 L"SCREEN\0" 00816 #if defined(FE_SB) 00817 L"TMP DBCS\0" 00818 L"SCREEN DBCS\0" 00819 L"EUDC\0" 00820 L"CONVAREA\0" 00821 L"IME\0" 00822 #endif 00823 ); 00824 Status = InitializeConsoleHandleTable(); 00825 if (!NT_SUCCESS(Status)) { 00826 return Status; 00827 } 00828 00829 Status = RtlInitializeCriticalSectionAndSpinCount(&ConsoleInitWindowsLock, 00830 0x80000000); 00831 if (!NT_SUCCESS(Status)) { 00832 return Status; 00833 } 00834 00835 // 00836 // Initialize Input thread local message queue 00837 // 00838 Status = RtlInitializeCriticalSectionAndSpinCount(&gInputThreadMsgLock, 00839 0x80000000); 00840 if (!NT_SUCCESS(Status)) { 00841 return Status; 00842 } 00843 00844 InitializeThreadMessages(); 00845 00846 #ifdef i386 00847 Status = RtlInitializeCriticalSectionAndSpinCount(&ConsoleVDMCriticalSection, 00848 0x80000000); 00849 if (!NT_SUCCESS(Status)) { 00850 return Status; 00851 } 00852 ConsoleVDMOnSwitching = NULL; 00853 #endif 00854 OEMCP = GetOEMCP(); 00855 WINDOWSCP = GetACP(); 00856 #if !defined(FE_SB) 00857 ConsoleOutputCP = OEMCP; 00858 #endif 00859 00860 InitializeFonts(); 00861 00862 InputThreadTlsIndex = TlsAlloc(); 00863 if (InputThreadTlsIndex == 0xFFFFFFFF) 00864 return STATUS_UNSUCCESSFUL; 00865 00866 #if defined(FE_SB) 00867 gfIsDBCSACP = !!IsAvailableFarEastCodePage(WINDOWSCP); 00868 #endif 00869 00870 return( STATUS_SUCCESS ); 00871 } 00872 00873 BOOL 00874 MapHandle( 00875 IN HANDLE ClientProcessHandle, 00876 IN HANDLE ServerHandle, 00877 OUT PHANDLE ClientHandle 00878 ) 00879 { 00880 // 00881 // map event handle into dll's handle space. 00882 // 00883 00884 return DuplicateHandle(NtCurrentProcess(), 00885 ServerHandle, 00886 ClientProcessHandle, 00887 ClientHandle, 00888 0, 00889 FALSE, 00890 DUPLICATE_SAME_ACCESS 00891 ); 00892 } 00893 00894 VOID 00895 AddProcessToList( 00896 IN OUT PCONSOLE_INFORMATION Console, 00897 IN OUT PCONSOLE_PROCESS_HANDLE ProcessHandleRecord, 00898 IN HANDLE ProcessHandle 00899 ) 00900 { 00901 ASSERT(!(Console->Flags & (CONSOLE_TERMINATING | CONSOLE_SHUTTING_DOWN))); 00902 00903 ProcessHandleRecord->ProcessHandle = ProcessHandle; 00904 ProcessHandleRecord->TerminateCount = 0; 00905 InsertHeadList(&Console->ProcessHandleList,&ProcessHandleRecord->ListLink); 00906 00907 SetProcessFocus(ProcessHandleRecord->Process, Console->Flags & CONSOLE_HAS_FOCUS); 00908 } 00909 00910 PCONSOLE_PROCESS_HANDLE 00911 FindProcessInList( 00912 IN PCONSOLE_INFORMATION Console, 00913 IN HANDLE ProcessHandle 00914 ) 00915 { 00916 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 00917 PLIST_ENTRY ListHead, ListNext; 00918 00919 ListHead = &Console->ProcessHandleList; 00920 ListNext = ListHead->Flink; 00921 while (ListNext != ListHead) { 00922 ProcessHandleRecord = CONTAINING_RECORD( ListNext, CONSOLE_PROCESS_HANDLE, ListLink ); 00923 if (ProcessHandleRecord->ProcessHandle == ProcessHandle) { 00924 return ProcessHandleRecord; 00925 } 00926 ListNext = ListNext->Flink; 00927 } 00928 return NULL; 00929 } 00930 00931 VOID 00932 RemoveProcessFromList( 00933 IN OUT PCONSOLE_INFORMATION Console, 00934 IN HANDLE ProcessHandle 00935 ) 00936 { 00937 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 00938 PLIST_ENTRY ListHead, ListNext; 00939 00940 ListHead = &Console->ProcessHandleList; 00941 ListNext = ListHead->Flink; 00942 while (ListNext != ListHead) { 00943 ProcessHandleRecord = CONTAINING_RECORD( ListNext, CONSOLE_PROCESS_HANDLE, ListLink ); 00944 ListNext = ListNext->Flink; 00945 if (ProcessHandleRecord->ProcessHandle == ProcessHandle) { 00946 RemoveEntryList(&ProcessHandleRecord->ListLink); 00947 ConsoleHeapFree(ProcessHandleRecord); 00948 return; 00949 } 00950 } 00951 ASSERT (FALSE); 00952 } 00953 00954 NTSTATUS 00955 SetUpConsole( 00956 IN OUT PCONSOLE_INFO ConsoleInfo, 00957 IN DWORD TitleLength, 00958 IN LPWSTR Title, 00959 IN LPWSTR CurDir, 00960 IN LPWSTR AppName, 00961 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 00962 IN BOOLEAN WindowVisible, 00963 IN PUNICODE_STRING pstrDesktopName 00964 ) 00965 { 00966 NTSTATUS Status; 00967 PCONSOLE_INFORMATION Console; 00968 DWORD ConsoleThreadId; 00969 HWINSTA hwinsta; 00970 HDESK hdesk; 00971 USEROBJECTFLAGS UserObjectFlags; 00972 DWORD Length; 00973 00974 // 00975 // Connect to the windowstation and desktop. 00976 // 00977 00978 if (!CsrImpersonateClient(NULL)) { 00979 return STATUS_BAD_IMPERSONATION_LEVEL; 00980 } 00981 00982 hdesk = NtUserResolveDesktop(CONSOLE_CLIENTPROCESSHANDLE(), 00983 pstrDesktopName, FALSE, &hwinsta); 00984 00985 CsrRevertToSelf(); 00986 00987 if (hdesk == NULL) { 00988 return STATUS_UNSUCCESSFUL; 00989 } 00990 00991 // 00992 // Need to initialize windows stuff once real console app starts. 00993 // This is because for the time being windows expects the first 00994 // app to be a windows app. 00995 // 00996 00997 Status = InitWindowsStuff(hdesk, &ConsoleThreadId); 00998 if (!NT_SUCCESS(Status)) { 00999 CloseDesktop(hdesk); 01000 CloseWindowStation(hwinsta); 01001 return Status; 01002 } 01003 01004 // 01005 // If the windowstation isn't visible, then neither is the window. 01006 // 01007 01008 if (WindowVisible) { 01009 if (GetUserObjectInformation(hwinsta, 01010 UOI_FLAGS, 01011 &UserObjectFlags, 01012 sizeof(UserObjectFlags), 01013 &Length)) { 01014 if (!(UserObjectFlags.dwFlags & WSF_VISIBLE)) { 01015 WindowVisible = FALSE; 01016 } 01017 } 01018 } 01019 01020 // 01021 // We need to see if we were spawned from a link. If we were, we 01022 // need to call back into the shell to try to get all the console 01023 // information from the link. 01024 // 01025 01026 LoadLinkInfo( ConsoleInfo, Title, &TitleLength, CurDir, AppName ); 01027 01028 LockConsoleHandleTable(); 01029 01030 Status = AllocateConsoleHandle(&ConsoleInfo->ConsoleHandle); 01031 if (!NT_SUCCESS(Status)) { 01032 UnlockConsoleHandleTable(); 01033 CloseDesktop(hdesk); 01034 CloseWindowStation(hwinsta); 01035 return Status; 01036 } 01037 01038 Status = AllocateConsole(ConsoleInfo->ConsoleHandle, 01039 Title, 01040 (USHORT)TitleLength, 01041 CONSOLE_CLIENTPROCESSHANDLE(), 01042 &ConsoleInfo->StdIn, 01043 &ConsoleInfo->StdOut, 01044 &ConsoleInfo->StdErr, 01045 ProcessData, 01046 ConsoleInfo, 01047 WindowVisible, 01048 ConsoleThreadId 01049 ); 01050 if (!NT_SUCCESS(Status)) { 01051 FreeConsoleHandle(ConsoleInfo->ConsoleHandle); 01052 UnlockConsoleHandleTable(); 01053 CloseDesktop(hdesk); 01054 CloseWindowStation(hwinsta); 01055 return Status; 01056 } 01057 CONSOLE_SETCONSOLEHANDLE(ConsoleInfo->ConsoleHandle); 01058 Status = DereferenceConsoleHandle(ConsoleInfo->ConsoleHandle,&Console); 01059 ASSERT (NT_SUCCESS(Status)); 01060 01061 // 01062 // increment console reference count 01063 // 01064 01065 Console->RefCount++; 01066 01067 // 01068 // Save the windowstation and desktop handles so they 01069 // can be used later 01070 // 01071 01072 Console->hWinSta = hwinsta; 01073 Console->hDesk = hdesk; 01074 01075 UnlockConsoleHandleTable(); 01076 01077 #if defined(FE_IME) 01078 if (CONSOLE_IS_IME_ENABLED()) 01079 { 01080 if (WindowVisible) 01081 { 01082 InitConsoleIMEStuff(Console->hDesk, ConsoleThreadId, Console); 01083 } 01084 } 01085 #endif 01086 01087 return Status; 01088 } 01089 01090 NTSTATUS 01091 ConsoleClientConnectRoutine( 01092 IN PCSR_PROCESS Process, 01093 IN OUT PVOID ConnectionInfo, 01094 IN OUT PULONG ConnectionInfoLength 01095 ) 01096 01097 /*++ 01098 01099 Routine Description: 01100 01101 This routine is called when a new process is created. For processes 01102 without parents, it creates the console. For processes with 01103 parents, it duplicates the handle table. 01104 01105 Arguments: 01106 01107 Process - Pointer to process structure. 01108 01109 ConnectionInfo - Pointer to connection info. 01110 01111 ConnectionInfoLength - Connection info length. 01112 01113 Return Value: 01114 01115 --*/ 01116 01117 { 01118 NTSTATUS Status; 01119 PCONSOLE_API_CONNECTINFO p = (PCONSOLE_API_CONNECTINFO)ConnectionInfo; 01120 PCONSOLE_INFORMATION Console; 01121 PCONSOLE_PER_PROCESS_DATA ProcessData; 01122 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 01123 CONSOLEWINDOWSTATIONPROCESS ConsoleWindowStationInfo; 01124 UNICODE_STRING strDesktopName; 01125 CONSOLE_PROCESS_INFO cpi; 01126 01127 if (p == NULL || 01128 *ConnectionInfoLength != sizeof( *p ) || 01129 p->AppNameLength > sizeof(p->AppName) || 01130 p->CurDirLength > sizeof(p->CurDir) || 01131 p->TitleLength > sizeof(p->Title)) { 01132 01133 KdPrint(("CONSRV: bad connection info\n")); 01134 ASSERT(FALSE); 01135 return( STATUS_UNSUCCESSFUL ); 01136 } 01137 01138 // 01139 // Make sure the strings are NULL terminated. 01140 // 01141 01142 p->AppName[NELEM(p->AppName) - 1] = 0; 01143 p->CurDir[NELEM(p->CurDir) - 1] = 0; 01144 p->Title[NELEM(p->Title) - 1] = 0; 01145 01146 if (CtrlRoutine == NULL) { 01147 CtrlRoutine = p->CtrlRoutine; 01148 } 01149 #if defined(FE_IME) 01150 if (ConsoleIMERoutine == NULL) { 01151 ConsoleIMERoutine = p->ConsoleIMERoutine; 01152 } 01153 #endif 01154 ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process); 01155 Console = NULL; 01156 01157 // 01158 // If this process is not a console app, stop right here - no 01159 // initialization is needed. Just need to remember that this 01160 // is not a console app so that we do no work during 01161 // ClientDisconnectRoutine(). 01162 // 01163 01164 Status = STATUS_SUCCESS; 01165 if ((CONSOLE_GETCONSOLEAPPFROMPROCESSDATA(ProcessData) = p->ConsoleApp)) { 01166 01167 // 01168 // First call off to USER so it unblocks any app waiting on a call 01169 // to WaitForInputIdle. This way apps calling WinExec() to exec console 01170 // apps will return right away. 01171 // 01172 01173 01174 /* 01175 * Bug 273518 - joejo 01176 * 01177 * Adding optimization to bug fix 01178 */ 01179 cpi.dwProcessID = HandleToUlong(CONSOLE_CLIENTPROCESSID()); 01180 cpi.dwFlags = (p->ConsoleInfo.ConsoleHandle != NULL) ? 0 : CPI_NEWPROCESSWINDOW; 01181 01182 NtUserConsoleControl(ConsoleNotifyConsoleApplication, 01183 &cpi, sizeof(CONSOLE_PROCESS_INFO)); 01184 01185 // 01186 // create console 01187 // 01188 01189 if (p->ConsoleInfo.ConsoleHandle == NULL) { 01190 ProcessHandleRecord = ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),sizeof(CONSOLE_PROCESS_HANDLE)); 01191 if (ProcessHandleRecord == NULL) { 01192 Status = STATUS_NO_MEMORY; 01193 goto ErrorExit; 01194 } 01195 01196 // 01197 // We are creating a new console, so derereference 01198 // the parent's console, if any. 01199 // 01200 01201 if (ProcessData->ConsoleHandle != NULL) { 01202 RemoveConsole(ProcessData, Process->ProcessHandle, 0); 01203 } 01204 01205 // 01206 // Get the desktop name. 01207 // 01208 01209 if (p->DesktopLength) { 01210 strDesktopName.Buffer = ConsoleHeapAlloc( 01211 MAKE_TAG( TMP_TAG ), 01212 p->DesktopLength); 01213 if (strDesktopName.Buffer == NULL) { 01214 Status = STATUS_NO_MEMORY; 01215 goto ErrorExit; 01216 } 01217 Status = NtReadVirtualMemory(Process->ProcessHandle, 01218 (PVOID)p->Desktop, 01219 strDesktopName.Buffer, 01220 p->DesktopLength, 01221 NULL 01222 ); 01223 if (!NT_SUCCESS(Status)) { 01224 ConsoleHeapFree(strDesktopName.Buffer); 01225 goto ErrorExit; 01226 } 01227 strDesktopName.MaximumLength = (USHORT)p->DesktopLength; 01228 strDesktopName.Length = (USHORT)(p->DesktopLength - sizeof(WCHAR)); 01229 } else { 01230 RtlInitUnicodeString(&strDesktopName, L"Default"); 01231 } 01232 01233 ProcessData->RootProcess = TRUE; 01234 Status = SetUpConsole(&p->ConsoleInfo, 01235 p->TitleLength, 01236 p->Title, 01237 p->CurDir, 01238 p->AppName, 01239 ProcessData, 01240 p->WindowVisible, 01241 &strDesktopName); 01242 if (p->DesktopLength) 01243 ConsoleHeapFree(strDesktopName.Buffer); 01244 if (!NT_SUCCESS(Status)) { 01245 goto ErrorExit; 01246 } 01247 01248 // Play the Open sound for console apps 01249 01250 ConsolePlaySound(); 01251 01252 Status = RevalidateConsole(p->ConsoleInfo.ConsoleHandle,&Console); 01253 ASSERT (NT_SUCCESS(Status)); 01254 } 01255 else { 01256 ProcessHandleRecord = NULL; 01257 ProcessData->RootProcess = FALSE; 01258 01259 Status = STATUS_SUCCESS; 01260 if (!(NT_SUCCESS(RevalidateConsole(p->ConsoleInfo.ConsoleHandle,&Console))) ) { 01261 Status = STATUS_PROCESS_IS_TERMINATING; 01262 goto ErrorExit; 01263 } 01264 01265 if (Console->Flags & CONSOLE_SHUTTING_DOWN) { 01266 Status = STATUS_PROCESS_IS_TERMINATING; 01267 goto ErrorExit; 01268 } 01269 01270 if (!MapHandle(CONSOLE_CLIENTPROCESSHANDLE(), 01271 Console->InitEvents[INITIALIZATION_SUCCEEDED], 01272 &p->ConsoleInfo.InitEvents[INITIALIZATION_SUCCEEDED] 01273 ) || 01274 !MapHandle(CONSOLE_CLIENTPROCESSHANDLE(), 01275 Console->InitEvents[INITIALIZATION_FAILED], 01276 &p->ConsoleInfo.InitEvents[INITIALIZATION_FAILED] 01277 ) || 01278 !MapHandle(CONSOLE_CLIENTPROCESSHANDLE(), 01279 Console->InputBuffer.InputWaitEvent, 01280 &p->ConsoleInfo.InputWaitHandle 01281 )) { 01282 Status = STATUS_NO_MEMORY; 01283 goto ErrorExit; 01284 } 01285 01286 ProcessHandleRecord = FindProcessInList(Console,CONSOLE_CLIENTPROCESSHANDLE()); 01287 if (ProcessHandleRecord) { 01288 ProcessHandleRecord->CtrlRoutine = p->CtrlRoutine; 01289 ProcessHandleRecord->PropRoutine = p->PropRoutine; 01290 ProcessHandleRecord = NULL; 01291 } 01292 } 01293 if (NT_SUCCESS(Status)) { 01294 01295 // 01296 // Associate the correct window station with client process 01297 // so they can do Global atom calls. 01298 // 01299 if (DuplicateHandle( NtCurrentProcess(), 01300 Console->hWinSta, 01301 Process->ProcessHandle, 01302 &ConsoleWindowStationInfo.hwinsta, 01303 0, 01304 FALSE, 01305 DUPLICATE_SAME_ACCESS 01306 ) 01307 ) { 01308 ConsoleWindowStationInfo.dwProcessId = HandleToUlong(CONSOLE_CLIENTPROCESSID()); 01309 NtUserConsoleControl(ConsoleWindowStationProcess, 01310 &ConsoleWindowStationInfo, sizeof(ConsoleWindowStationInfo)); 01311 01312 } 01313 01314 if (ProcessHandleRecord) { 01315 ProcessHandleRecord->Process = Process; 01316 ProcessHandleRecord->CtrlRoutine = p->CtrlRoutine; 01317 ProcessHandleRecord->PropRoutine = p->PropRoutine; 01318 AddProcessToList(Console,ProcessHandleRecord,CONSOLE_CLIENTPROCESSHANDLE()); 01319 } 01320 SetProcessForegroundRights(Process, 01321 Console->Flags & CONSOLE_HAS_FOCUS); 01322 AllocateCommandHistory(Console, 01323 p->AppNameLength, 01324 p->AppName, 01325 CONSOLE_CLIENTPROCESSHANDLE()); 01326 UnlockConsole(Console); 01327 01328 } else { 01329 ErrorExit: 01330 CONSOLE_SETCONSOLEAPPFROMPROCESSDATA(ProcessData,FALSE); 01331 if (ProcessHandleRecord) 01332 ConsoleHeapFree(ProcessHandleRecord); 01333 if (Console) { 01334 UnlockConsole(Console); 01335 } 01336 if (ProcessData->ConsoleHandle != NULL) { 01337 RemoveConsole(ProcessData, Process->ProcessHandle, 0); 01338 } 01339 } 01340 } else if (ProcessData->ConsoleHandle != NULL) { 01341 01342 // 01343 // This is a non-console app with a reference to a 01344 // reference to a parent console. Dereference the 01345 // console. 01346 // 01347 01348 RemoveConsole(ProcessData, Process->ProcessHandle, 0); 01349 } 01350 01351 return( Status ); 01352 } 01353 01354 NTSTATUS 01355 RemoveConsole( 01356 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 01357 IN HANDLE ProcessHandle, 01358 IN HANDLE ProcessId 01359 ) 01360 { 01361 ULONG i; 01362 PHANDLE_DATA HandleData; 01363 NTSTATUS Status; 01364 PCONSOLE_INFORMATION Console; 01365 01366 Status = RevalidateConsole(ProcessData->ConsoleHandle, &Console); 01367 01368 // 01369 // If this process isn't using the console, error. 01370 // 01371 01372 if (!NT_SUCCESS(Status)) { 01373 ASSERT(FALSE); 01374 return Status; 01375 } 01376 01377 if (Console->Flags & CONSOLE_NOTIFY_LAST_CLOSE) { 01378 if (Console->ProcessIdLastNotifyClose == ProcessId) { 01379 // if this process is the one who wants last close notification, 01380 // remove it. 01381 Console->Flags &= ~CONSOLE_NOTIFY_LAST_CLOSE; 01382 NtClose(Console->hProcessLastNotifyClose); 01383 } else if (ProcessData->RootProcess) { 01384 // notify the ntvdm process to terminate if the console root 01385 // process is going away. 01386 HANDLE ConsoleHandle; 01387 CONSOLE_PROCESS_TERMINATION_RECORD ProcessHandleList; 01388 01389 Console->Flags &= ~CONSOLE_NOTIFY_LAST_CLOSE; 01390 ConsoleHandle = Console->ConsoleHandle; 01391 ProcessHandleList.ProcessHandle = Console->hProcessLastNotifyClose; 01392 ProcessHandleList.TerminateCount = 0; 01393 ProcessHandleList.CtrlRoutine = CtrlRoutine; 01394 UnlockConsole(Console); 01395 CreateCtrlThread(&ProcessHandleList, 01396 1, 01397 NULL, 01398 SYSTEM_ROOT_CONSOLE_EVENT, 01399 TRUE); 01400 NtClose(ProcessHandleList.ProcessHandle); 01401 Status = RevalidateConsole(ConsoleHandle, &Console); 01402 ASSERT(NT_SUCCESS(Status)); 01403 if (!NT_SUCCESS(Status)) { 01404 return STATUS_SUCCESS; 01405 } 01406 } 01407 } 01408 01409 if (Console->VDMProcessId == ProcessId && 01410 (Console->Flags & CONSOLE_VDM_REGISTERED)) { 01411 Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; 01412 UnregisterVDM(Console); 01413 } 01414 01415 if (ProcessHandle != NULL) { 01416 RemoveProcessFromList(Console,ProcessHandle); 01417 FreeCommandHistory(Console,ProcessHandle); 01418 } 01419 01420 ASSERT(Console->RefCount); 01421 01422 // 01423 // close the process's handles. 01424 // 01425 01426 for (i=0;i<ProcessData->HandleTableSize;i++) { 01427 if (ProcessData->HandleTablePtr[i].HandleType != CONSOLE_FREE_HANDLE) { 01428 Status = DereferenceIoHandleNoCheck(ProcessData, 01429 (HANDLE) i, 01430 &HandleData 01431 ); 01432 ASSERT (NT_SUCCESS(Status)); 01433 if (HandleData->HandleType & CONSOLE_INPUT_HANDLE) { 01434 Status = CloseInputHandle(ProcessData,Console,HandleData,(HANDLE) i); 01435 } 01436 else { 01437 Status = CloseOutputHandle(ProcessData,Console,HandleData,(HANDLE) i,FALSE); 01438 } 01439 } 01440 } 01441 FreeProcessData(ProcessData); 01442 ProcessData->ConsoleHandle = NULL; 01443 01444 // 01445 // decrement the console reference count. free the console if it goes to 01446 // zero. 01447 // 01448 01449 Console->RefCount--; 01450 if (Console->RefCount == 0) { 01451 01452 #if defined(FE_IME) 01453 01454 PCONVERSIONAREA_INFORMATION ConvAreaInfo; 01455 PCONVERSIONAREA_INFORMATION ConvAreaInfoNext; 01456 01457 ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot; 01458 while(ConvAreaInfo) { 01459 ConvAreaInfoNext = ConvAreaInfo->ConvAreaNext; 01460 FreeConvAreaScreenBuffer(ConvAreaInfo->ScreenBuffer); 01461 ConsoleHeapFree(ConvAreaInfo); 01462 ConvAreaInfo = ConvAreaInfoNext; 01463 } 01464 01465 if (Console->ConsoleIme.NumberOfConvAreaCompStr) { 01466 ConsoleHeapFree(Console->ConsoleIme.ConvAreaCompStr); 01467 } 01468 if (Console->ConsoleIme.CompStrData) { 01469 ConsoleHeapFree(Console->ConsoleIme.CompStrData); 01470 } 01471 #endif 01472 FreeCon(Console); 01473 } 01474 else { 01475 UnlockConsole(Console); 01476 } 01477 return( STATUS_SUCCESS ); 01478 } 01479 01480 //NTSTATUS 01481 VOID 01482 ConsoleClientDisconnectRoutine( 01483 IN PCSR_PROCESS Process 01484 ) 01485 01486 /*++ 01487 01488 Routine Description: 01489 01490 This routine is called when a process is destroyed. It closes the 01491 process's handles and frees the console if it's the last reference. 01492 01493 Arguments: 01494 01495 Process - Pointer to process structure. 01496 01497 Return Value: 01498 01499 --*/ 01500 01501 { 01502 PCONSOLE_PER_PROCESS_DATA ProcessData; 01503 01504 #if 0 01505 OutputDebugString("entering ConsoleClientDisconnectRoutine\n"); 01506 #endif 01507 ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process); 01508 01509 // 01510 // If this process is not a console app, stop right here - no 01511 // disconnect processing is needed, because this app didn't create 01512 // or connect to an existing console. 01513 // 01514 01515 if ( ProcessData->ConsoleHandle == NULL ) { 01516 #if defined(FE_IME) 01517 if (ProcessData->hDesk ) 01518 { 01519 // 01520 // If this process is a Console IME, 01521 // should unregister console IME on this desktop. 01522 // 01523 RemoveConsoleIME(Process, HandleToUlong(Process->ClientId.UniqueThread)); 01524 } 01525 #endif 01526 return; 01527 } 01528 01529 RemoveConsole(ProcessData, 01530 CONSOLE_FROMPROCESSPROCESSHANDLE(Process), 01531 Process->ClientId.UniqueProcess); 01532 CONSOLE_SETCONSOLEAPPFROMPROCESSDATA(ProcessData,FALSE); 01533 return; 01534 } 01535 01536 ULONG 01537 SrvAllocConsole( 01538 IN OUT PCSR_API_MSG m, 01539 IN OUT PCSR_REPLY_STATUS ReplyStatus 01540 ) 01541 { 01542 PCONSOLE_ALLOC_MSG a = (PCONSOLE_ALLOC_MSG)&m->u.ApiMessageData; 01543 PCONSOLE_PER_PROCESS_DATA ProcessData; 01544 NTSTATUS Status; 01545 PCONSOLE_INFORMATION Console; 01546 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 01547 PCSR_PROCESS Process; 01548 UNICODE_STRING strDesktopName; 01549 01550 ProcessData = CONSOLE_PERPROCESSDATA(); 01551 ASSERT(!CONSOLE_GETCONSOLEAPPFROMPROCESSDATA(ProcessData)); 01552 01553 if (!CsrValidateMessageBuffer(m, &a->Title, a->TitleLength, sizeof(BYTE)) || 01554 !CsrValidateMessageBuffer(m, &a->Desktop, a->DesktopLength, sizeof(BYTE)) || 01555 !CsrValidateMessageBuffer(m, &a->CurDir, a->CurDirLength, sizeof(BYTE)) || 01556 !CsrValidateMessageBuffer(m, &a->AppName, a->AppNameLength, sizeof(BYTE)) || 01557 !CsrValidateMessageBuffer(m, &a->ConsoleInfo, sizeof(*a->ConsoleInfo), sizeof(BYTE))) { 01558 01559 return STATUS_INVALID_PARAMETER; 01560 } 01561 01562 Process = (PCSR_PROCESS)(CSR_SERVER_QUERYCLIENTTHREAD()->Process); 01563 if (a->DesktopLength) 01564 RtlInitUnicodeString(&strDesktopName, a->Desktop); 01565 else 01566 RtlInitUnicodeString(&strDesktopName, L"Default"); 01567 01568 ProcessHandleRecord = ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),sizeof(CONSOLE_PROCESS_HANDLE)); 01569 if (ProcessHandleRecord == NULL) { 01570 return (ULONG)STATUS_NO_MEMORY; 01571 } 01572 01573 Status = SetUpConsole(a->ConsoleInfo, 01574 a->TitleLength, 01575 a->Title, 01576 a->CurDir, 01577 a->AppName, 01578 ProcessData, 01579 TRUE, 01580 &strDesktopName); 01581 if (!NT_SUCCESS(Status)) { 01582 ConsoleHeapFree(ProcessHandleRecord); 01583 return Status; 01584 } 01585 CONSOLE_SETCONSOLEAPP(TRUE); 01586 Process->Flags |= CSR_PROCESS_CONSOLEAPP; 01587 Status = RevalidateConsole(a->ConsoleInfo->ConsoleHandle,&Console); 01588 ASSERT (NT_SUCCESS(Status)); 01589 ProcessHandleRecord->Process = CSR_SERVER_QUERYCLIENTTHREAD()->Process; 01590 ProcessHandleRecord->CtrlRoutine = a->CtrlRoutine; 01591 ProcessHandleRecord->PropRoutine = a->PropRoutine; 01592 ASSERT (!(Console->Flags & CONSOLE_SHUTTING_DOWN)); 01593 AddProcessToList(Console,ProcessHandleRecord,CONSOLE_CLIENTPROCESSHANDLE()); 01594 SetProcessForegroundRights(Process, 01595 Console->Flags & CONSOLE_HAS_FOCUS); 01596 (HANDLE) AllocateCommandHistory(Console, 01597 a->AppNameLength, 01598 a->AppName, 01599 CONSOLE_CLIENTPROCESSHANDLE()); 01600 01601 UnlockConsole(Console); 01602 01603 return STATUS_SUCCESS; 01604 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01605 } 01606 01607 ULONG 01608 SrvFreeConsole( 01609 IN OUT PCSR_API_MSG m, 01610 IN OUT PCSR_REPLY_STATUS ReplyStatus 01611 ) 01612 { 01613 PCONSOLE_FREE_MSG a = (PCONSOLE_FREE_MSG)&m->u.ApiMessageData; 01614 PCONSOLE_PER_PROCESS_DATA ProcessData; 01615 NTSTATUS Status; 01616 01617 ProcessData = CONSOLE_PERPROCESSDATA(); 01618 ASSERT (CONSOLE_GETCONSOLEAPPFROMPROCESSDATA(ProcessData)); 01619 01620 ASSERT(CONSOLE_GETCONSOLEHANDLEFROMPROCESSDATA(ProcessData)==a->ConsoleHandle); 01621 01622 Status = RemoveConsole(ProcessData, 01623 CONSOLE_CLIENTPROCESSHANDLE(), 01624 CONSOLE_CLIENTPROCESSID()); 01625 01626 if (NT_SUCCESS(Status)) { 01627 CONSOLE_SETCONSOLEAPP(FALSE); 01628 } 01629 01630 return Status; 01631 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01632 } 01633 01634 NTSTATUS 01635 MyRegOpenKey( 01636 IN HANDLE hKey, 01637 IN LPWSTR lpSubKey, 01638 OUT PHANDLE phResult 01639 ) 01640 { 01641 OBJECT_ATTRIBUTES Obja; 01642 UNICODE_STRING SubKey; 01643 01644 // 01645 // Convert the subkey to a counted Unicode string. 01646 // 01647 01648 RtlInitUnicodeString( &SubKey, lpSubKey ); 01649 01650 // 01651 // Initialize the OBJECT_ATTRIBUTES structure and open the key. 01652 // 01653 01654 InitializeObjectAttributes( 01655 &Obja, 01656 &SubKey, 01657 OBJ_CASE_INSENSITIVE, 01658 hKey, 01659 NULL 01660 ); 01661 01662 return NtOpenKey( 01663 phResult, 01664 KEY_READ, 01665 &Obja 01666 ); 01667 } 01668 01669 NTSTATUS 01670 MyRegQueryValue( 01671 IN HANDLE hKey, 01672 IN LPWSTR lpValueName, 01673 IN DWORD dwValueLength, 01674 OUT LPBYTE lpData 01675 ) 01676 { 01677 UNICODE_STRING ValueName; 01678 ULONG BufferLength; 01679 ULONG ResultLength; 01680 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 01681 NTSTATUS Status; 01682 01683 // 01684 // Convert the subkey to a counted Unicode string. 01685 // 01686 01687 RtlInitUnicodeString( &ValueName, lpValueName ); 01688 01689 BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + dwValueLength; 01690 KeyValueInformation = ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),BufferLength); 01691 if (KeyValueInformation == NULL) 01692 return STATUS_NO_MEMORY; 01693 01694 Status = NtQueryValueKey( 01695 hKey, 01696 &ValueName, 01697 KeyValuePartialInformation, 01698 KeyValueInformation, 01699 BufferLength, 01700 &ResultLength 01701 ); 01702 if (NT_SUCCESS(Status)) { 01703 ASSERT(KeyValueInformation->DataLength <= dwValueLength); 01704 RtlCopyMemory(lpData, 01705 KeyValueInformation->Data, 01706 KeyValueInformation->DataLength); 01707 if (KeyValueInformation->Type == REG_SZ || 01708 KeyValueInformation->Type == REG_MULTI_SZ 01709 ) { 01710 if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwValueLength) { 01711 KeyValueInformation->DataLength -= sizeof(WCHAR); 01712 } 01713 lpData[KeyValueInformation->DataLength++] = 0; 01714 lpData[KeyValueInformation->DataLength] = 0; 01715 } 01716 } 01717 ConsoleHeapFree(KeyValueInformation); 01718 return Status; 01719 } 01720 01721 #if defined(FE_SB) 01722 NTSTATUS 01723 MyRegQueryValueEx( 01724 IN HANDLE hKey, 01725 IN LPWSTR lpValueName, 01726 IN DWORD dwValueLength, 01727 OUT LPBYTE lpData, 01728 OUT LPDWORD lpDataLength 01729 ) 01730 { 01731 UNICODE_STRING ValueName; 01732 ULONG BufferLength; 01733 ULONG ResultLength; 01734 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 01735 NTSTATUS Status; 01736 01737 // 01738 // Convert the subkey to a counted Unicode string. 01739 // 01740 01741 RtlInitUnicodeString( &ValueName, lpValueName ); 01742 01743 BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + dwValueLength; 01744 KeyValueInformation = ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),BufferLength); 01745 if (KeyValueInformation == NULL) 01746 return STATUS_NO_MEMORY; 01747 01748 Status = NtQueryValueKey( 01749 hKey, 01750 &ValueName, 01751 KeyValuePartialInformation, 01752 KeyValueInformation, 01753 BufferLength, 01754 &ResultLength 01755 ); 01756 if (NT_SUCCESS(Status)) { 01757 ASSERT(KeyValueInformation->DataLength <= dwValueLength); 01758 RtlCopyMemory(lpData, 01759 KeyValueInformation->Data, 01760 KeyValueInformation->DataLength); 01761 if (lpDataLength) 01762 { 01763 *lpDataLength = KeyValueInformation->DataLength; 01764 } 01765 } 01766 ConsoleHeapFree(KeyValueInformation); 01767 return Status; 01768 } 01769 01770 NTSTATUS 01771 MyRegEnumValue( 01772 IN HANDLE hKey, 01773 IN DWORD dwIndex, 01774 OUT DWORD dwValueLength, 01775 OUT LPWSTR lpValueName, 01776 OUT DWORD dwDataLength, 01777 OUT LPBYTE lpData 01778 ) 01779 { 01780 ULONG BufferLength; 01781 ULONG ResultLength; 01782 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 01783 NTSTATUS Status; 01784 01785 // 01786 // Convert the subkey to a counted Unicode string. 01787 // 01788 01789 BufferLength = sizeof(KEY_VALUE_FULL_INFORMATION) + dwValueLength + dwDataLength; 01790 KeyValueInformation = ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),BufferLength); 01791 if (KeyValueInformation == NULL) 01792 return STATUS_NO_MEMORY; 01793 01794 Status = NtEnumerateValueKey( 01795 hKey, 01796 dwIndex, 01797 KeyValueFullInformation, 01798 KeyValueInformation, 01799 BufferLength, 01800 &ResultLength 01801 ); 01802 if (NT_SUCCESS(Status)) { 01803 ASSERT(KeyValueInformation->NameLength <= dwValueLength); 01804 RtlMoveMemory(lpValueName, 01805 KeyValueInformation->Name, 01806 KeyValueInformation->NameLength); 01807 lpValueName[ KeyValueInformation->NameLength >> 1 ] = UNICODE_NULL; 01808 01809 01810 ASSERT(KeyValueInformation->DataLength <= dwDataLength); 01811 RtlMoveMemory(lpData, 01812 (PBYTE)KeyValueInformation + KeyValueInformation->DataOffset, 01813 KeyValueInformation->DataLength); 01814 if (KeyValueInformation->Type == REG_SZ) { 01815 if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwDataLength) { 01816 KeyValueInformation->DataLength -= sizeof(WCHAR); 01817 } 01818 lpData[KeyValueInformation->DataLength++] = 0; 01819 lpData[KeyValueInformation->DataLength] = 0; 01820 } 01821 } 01822 ConsoleHeapFree(KeyValueInformation); 01823 return Status; 01824 } 01825 #endif 01826 01827 #define SYSTEM_ROOT (L"%SystemRoot%") 01828 #define SYSTEM_ROOT_LENGTH (sizeof(SYSTEM_ROOT) - sizeof(WCHAR)) 01829 01830 LPWSTR 01831 TranslateConsoleTitle( 01832 LPWSTR ConsoleTitle, 01833 PUSHORT pcbTranslatedTitle, 01834 BOOL Unexpand, 01835 BOOL Substitute 01836 ) 01837 /*++ 01838 01839 Routine Description: 01840 01841 This routine translates path characters into '_' characters because 01842 the NT registry apis do not allow the creation of keys with 01843 names that contain path characters. It also converts absolute paths 01844 into %SystemRoot% relative ones. As an example, if both behaviors were 01845 specified it would convert a title like C:\WINNT\System32\cmd.exe to 01846 %SystemRoot%_System32_cmd.exe. 01847 01848 Arguments: 01849 01850 ConsoleTitle - Pointer to string to translate. 01851 01852 pcbTranslatedTitle - On return, contains size of translated title. 01853 01854 Unexpand - Convert absolute path to %SystemRoot% relative one. 01855 01856 Substitute - Replace '\' with '_' in path. 01857 01858 Return Value: 01859 01860 Pointer to translated title or NULL. 01861 01862 Note: 01863 01864 This routine allocates a buffer that must be freed. 01865 01866 --*/ 01867 { 01868 USHORT cbConsoleTitle,i; 01869 USHORT cbSystemRoot; 01870 LPWSTR TranslatedConsoleTitle,Tmp; 01871 01872 cbConsoleTitle = (USHORT)((lstrlenW(ConsoleTitle) + 1) * sizeof(WCHAR)); 01873 cbSystemRoot = (USHORT)(lstrlenW(USER_SHARED_DATA->NtSystemRoot) * sizeof(WCHAR)); 01874 01875 if (Unexpand && !MyStringCompareW(ConsoleTitle, 01876 USER_SHARED_DATA->NtSystemRoot, 01877 cbSystemRoot, 01878 TRUE)) { 01879 cbConsoleTitle -= cbSystemRoot; 01880 (PBYTE)ConsoleTitle += cbSystemRoot; 01881 cbSystemRoot = SYSTEM_ROOT_LENGTH; 01882 } else { 01883 cbSystemRoot = 0; 01884 } 01885 01886 Tmp = TranslatedConsoleTitle = ConsoleHeapAlloc(MAKE_TAG( TITLE_TAG ),cbSystemRoot + cbConsoleTitle); 01887 if (TranslatedConsoleTitle == NULL) { 01888 return NULL; 01889 } 01890 01891 RtlCopyMemory(TranslatedConsoleTitle, SYSTEM_ROOT, cbSystemRoot); 01892 (PBYTE)TranslatedConsoleTitle += cbSystemRoot; 01893 01894 for (i=0;i<cbConsoleTitle;i+=sizeof(WCHAR)) { 01895 if (Substitute && *ConsoleTitle == '\\') { 01896 *TranslatedConsoleTitle++ = (WCHAR)'_'; 01897 } else { 01898 *TranslatedConsoleTitle++ = *ConsoleTitle; 01899 } 01900 ConsoleTitle++; 01901 } 01902 01903 if (pcbTranslatedTitle) { 01904 *pcbTranslatedTitle = cbSystemRoot + cbConsoleTitle; 01905 } 01906 01907 return Tmp; 01908 } 01909 01910 01911 ULONG 01912 ConsoleClientShutdown( 01913 PCSR_PROCESS Process, 01914 ULONG Flags, 01915 BOOLEAN fFirstPass 01916 ) 01917 { 01918 PCONSOLE_INFORMATION Console; 01919 PCONSOLE_PER_PROCESS_DATA ProcessData; 01920 NTSTATUS Status; 01921 HWND hWnd; 01922 HANDLE TerminationEvent; 01923 HANDLE ConsoleHandle; 01924 NTSTATUS WaitStatus; 01925 USERTHREAD_USEDESKTOPINFO utudi; 01926 01927 // 01928 // Find the console associated with this process 01929 // 01930 01931 ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process); 01932 01933 // 01934 // If this process is not a console app, stop right here unless 01935 // this is the second pass of shutdown, in which case we'll take 01936 // it. 01937 // 01938 01939 if (!ProcessData || !CONSOLE_GETCONSOLEAPPFROMPROCESSDATA(ProcessData)) { 01940 #if defined(FE_IME) 01941 if (fFirstPass && 01942 (ProcessData->ConsoleHandle == NULL) && 01943 (ProcessData->hDesk != NULL)) 01944 { 01945 // 01946 // If this process is a Console IME, 01947 // should unregister console IME on this desktop. 01948 // 01949 RemoveConsoleIME(Process, HandleToUlong(Process->ClientId.UniqueThread)); 01950 } 01951 #endif 01952 if (fFirstPass) { 01953 return SHUTDOWN_UNKNOWN_PROCESS; 01954 } 01955 return NonConsoleProcessShutdown(Process, Flags); 01956 } 01957 01958 // 01959 // Find the console structure pointer. 01960 // 01961 01962 ConsoleHandle = CONSOLE_GETCONSOLEHANDLEFROMPROCESSDATA(ProcessData); 01963 Status = RevalidateConsole( 01964 ConsoleHandle, 01965 &Console); 01966 01967 if (!NT_SUCCESS(Status)) { 01968 return SHUTDOWN_UNKNOWN_PROCESS; 01969 } 01970 01971 // 01972 // If this is the invisible WOW console, return UNKNOWN so USER 01973 // enumerates 16-bit gui apps. 01974 // 01975 01976 if ((Console->Flags & CONSOLE_NO_WINDOW) && 01977 (Console->Flags & CONSOLE_WOW_REGISTERED)) { 01978 UnlockConsole(Console); 01979 return SHUTDOWN_UNKNOWN_PROCESS; 01980 } 01981 01982 // 01983 // Sometimes the console structure is around even though the 01984 // hWnd has been NULLed out. In this case, go to non-console 01985 // process shutdown. 01986 // 01987 01988 hWnd = Console->hWnd; 01989 if (hWnd == NULL || !IsWindow(hWnd)) { 01990 UnlockConsole(Console); 01991 return NonConsoleProcessShutdown(Process, Flags); 01992 } 01993 01994 // 01995 // Make a copy of the console termination event 01996 // 01997 01998 Status = NtDuplicateObject(NtCurrentProcess(), 01999 Console->TerminationEvent, 02000 NtCurrentProcess(), 02001 &TerminationEvent, 02002 0, 02003 FALSE, 02004 DUPLICATE_SAME_ACCESS 02005 ); 02006 if (!NT_SUCCESS(Status)) { 02007 UnlockConsole(Console); 02008 return NonConsoleProcessShutdown(Process, Flags); 02009 } 02010 02011 // 02012 // Attach to the desktop. 02013 // 02014 02015 utudi.hThread = Console->InputThreadInfo->ThreadHandle; 02016 utudi.drdRestore.pdeskRestore = NULL; 02017 Status = NtUserSetInformationThread(NtCurrentThread(), 02018 UserThreadUseDesktop, 02019 &utudi, 02020 sizeof(utudi)); 02021 02022 UnlockConsole(Console); 02023 if (!NT_SUCCESS(Status)) { 02024 return NonConsoleProcessShutdown(Process, Flags); 02025 } 02026 02027 // 02028 // We're done looking at this process structure, so dereference it. 02029 // 02030 CsrDereferenceProcess(Process); 02031 02032 // 02033 // Synchronously talk to this console. 02034 // 02035 02036 Status = ShutdownConsole(ConsoleHandle, Flags); 02037 02038 // 02039 // Detach from the desktop. 02040 // 02041 02042 utudi.hThread = NULL; 02043 NtUserSetInformationThread(NtCurrentThread(), 02044 UserThreadUseDesktop, 02045 &utudi, 02046 sizeof(utudi)); 02047 02048 // 02049 // If Status == STATUS_PROCESS_IS_TERMINATING, then we should wait 02050 // for the console to exit. 02051 // 02052 02053 if (Status == STATUS_PROCESS_IS_TERMINATING) { 02054 WaitStatus = InternalWaitCancel(TerminationEvent, 500000); 02055 if (WaitStatus == STATUS_WAIT_1) { 02056 Status = SHUTDOWN_CANCEL; 02057 } else if (WaitStatus != STATUS_TIMEOUT) { 02058 Status = SHUTDOWN_KNOWN_PROCESS; 02059 } else { 02060 #if DBG 02061 PLIST_ENTRY ListHead, ListNext; 02062 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 02063 PCSR_PROCESS Process; 02064 02065 RIPMSG0(RIP_ERROR | RIP_THERESMORE, "********************************************"); 02066 RIPMSG1(RIP_ERROR | RIP_THERESMORE, "Shutdown wait timed out on console %p", Console); 02067 RIPMSG1(RIP_ERROR | RIP_THERESMORE, "Reference count is %d", Console->RefCount); 02068 RIPMSG0(RIP_ERROR | RIP_THERESMORE, "Dump these processes and see if they're hung"); 02069 ListHead = &Console->ProcessHandleList; 02070 ListNext = ListHead->Flink; 02071 while (ListNext != ListHead) { 02072 ProcessHandleRecord = CONTAINING_RECORD(ListNext, CONSOLE_PROCESS_HANDLE, ListLink); 02073 Process = ProcessHandleRecord->Process; 02074 RIPMSG2(RIP_ERROR | RIP_THERESMORE, "CsrProcess = %p ProcessId = %x", Process, Process->ClientId.UniqueProcess); 02075 ListNext = ListNext->Flink; 02076 } 02077 RIPMSG0(RIP_ERROR, "********************************************"); 02078 #endif 02079 Status = SHUTDOWN_CANCEL; 02080 } 02081 } 02082 NtClose(TerminationEvent); 02083 02084 return Status; 02085 } 02086 02087 ULONG 02088 NonConsoleProcessShutdown( 02089 PCSR_PROCESS Process, 02090 DWORD dwFlags 02091 ) 02092 { 02093 CONSOLE_PROCESS_TERMINATION_RECORD TerminateRecord; 02094 DWORD EventType; 02095 BOOL Success; 02096 HANDLE ProcessHandle; 02097 02098 Success = DuplicateHandle(NtCurrentProcess(), 02099 Process->ProcessHandle, 02100 NtCurrentProcess(), 02101 &ProcessHandle, 02102 0, 02103 FALSE, 02104 DUPLICATE_SAME_ACCESS); 02105 02106 if (!Success) 02107 ProcessHandle = Process->ProcessHandle; 02108 02109 TerminateRecord.ProcessHandle = ProcessHandle; 02110 TerminateRecord.TerminateCount = 0; 02111 TerminateRecord.CtrlRoutine = CtrlRoutine; 02112 02113 CsrDereferenceProcess(Process); 02114 02115 EventType = CTRL_LOGOFF_EVENT; 02116 if (dwFlags & EWX_SHUTDOWN) 02117 EventType = CTRL_SHUTDOWN_EVENT; 02118 02119 CreateCtrlThread(&TerminateRecord, 02120 1, 02121 NULL, 02122 EventType, 02123 TRUE); 02124 02125 if (Success) 02126 CloseHandle(ProcessHandle); 02127 02128 return SHUTDOWN_KNOWN_PROCESS; 02129 } 02130 02131 VOID 02132 InitializeConsoleAttributes( VOID ) 02133 02134 /*++ 02135 02136 Routine Description: 02137 02138 This routine initializes default attributes from the current 02139 user's registry values. It gets called during logon/logoff. 02140 02141 Arguments: 02142 02143 none 02144 02145 Return Value: 02146 02147 none 02148 02149 --*/ 02150 02151 { 02152 // 02153 // Store default values in structure and mark it 02154 // as invalid (by resetting LastWriteTime). 02155 // 02156 02157 DefaultRegInfo.ScreenFill.Attributes = 0x07; // white on black 02158 DefaultRegInfo.ScreenFill.Char.UnicodeChar = (WCHAR)' '; 02159 DefaultRegInfo.PopupFill.Attributes = 0xf5; // purple on white 02160 DefaultRegInfo.PopupFill.Char.UnicodeChar = (WCHAR)' '; 02161 DefaultRegInfo.InsertMode = FALSE; 02162 DefaultRegInfo.QuickEdit = FALSE; 02163 DefaultRegInfo.AutoPosition = TRUE; 02164 DefaultRegInfo.FullScreen = FALSE; 02165 DefaultRegInfo.ScreenBufferSize.X = 80; 02166 DefaultRegInfo.ScreenBufferSize.Y = 25; 02167 DefaultRegInfo.WindowSize.X = 80; 02168 DefaultRegInfo.WindowSize.Y = 25; 02169 DefaultRegInfo.WindowOrigin.X = 0; 02170 DefaultRegInfo.WindowOrigin.Y = 0; 02171 DefaultRegInfo.FontSize.X = 0; 02172 DefaultRegInfo.FontSize.Y = 0; 02173 DefaultRegInfo.FontFamily = 0; 02174 DefaultRegInfo.FontWeight = 0; 02175 DefaultRegInfo.FaceName[0] = L'\0'; 02176 DefaultRegInfo.CursorSize = CURSOR_SMALL_SIZE; 02177 DefaultRegInfo.HistoryBufferSize = DEFAULT_NUMBER_OF_COMMANDS; 02178 DefaultRegInfo.NumberOfHistoryBuffers = DEFAULT_NUMBER_OF_BUFFERS; 02179 DefaultRegInfo.HistoryNoDup = FALSE; 02180 DefaultRegInfo.ColorTable[ 0] = RGB(0, 0, 0 ); 02181 DefaultRegInfo.ColorTable[ 1] = RGB(0, 0, 0x80); 02182 DefaultRegInfo.ColorTable[ 2] = RGB(0, 0x80,0 ); 02183 DefaultRegInfo.ColorTable[ 3] = RGB(0, 0x80,0x80); 02184 DefaultRegInfo.ColorTable[ 4] = RGB(0x80,0, 0 ); 02185 DefaultRegInfo.ColorTable[ 5] = RGB(0x80,0, 0x80); 02186 DefaultRegInfo.ColorTable[ 6] = RGB(0x80,0x80,0 ); 02187 DefaultRegInfo.ColorTable[ 7] = RGB(0xC0,0xC0,0xC0); 02188 DefaultRegInfo.ColorTable[ 8] = RGB(0x80,0x80,0x80); 02189 DefaultRegInfo.ColorTable[ 9] = RGB(0, 0, 0xFF); 02190 DefaultRegInfo.ColorTable[10] = RGB(0, 0xFF,0 ); 02191 DefaultRegInfo.ColorTable[11] = RGB(0, 0xFF,0xFF); 02192 DefaultRegInfo.ColorTable[12] = RGB(0xFF,0, 0 ); 02193 DefaultRegInfo.ColorTable[13] = RGB(0xFF,0, 0xFF); 02194 DefaultRegInfo.ColorTable[14] = RGB(0xFF,0xFF,0 ); 02195 DefaultRegInfo.ColorTable[15] = RGB(0xFF,0xFF,0xFF); 02196 #if defined(FE_SB) // scotthsu 02197 DefaultRegInfo.CodePage = OEMCP; 02198 #endif 02199 DefaultRegInfo.LastWriteTime = 0; 02200 02201 // 02202 // Get system metrics for this user 02203 // 02204 02205 InitializeSystemMetrics(); 02206 } 02207 02208 02209 VOID 02210 GetRegistryValues( 02211 IN LPWSTR ConsoleTitle, 02212 OUT PCONSOLE_REGISTRY_INFO RegInfo 02213 ) 02214 02215 /*++ 02216 02217 Routine Description: 02218 02219 This routine reads in values from the registry and places them 02220 in the supplied structure. 02221 02222 Arguments: 02223 02224 ConsoleTitle - name of subkey to open 02225 02226 RegInfo - pointer to structure to receive information 02227 02228 Return Value: 02229 02230 none 02231 02232 --*/ 02233 02234 { 02235 HANDLE hCurrentUserKey; 02236 HANDLE hConsoleKey; 02237 HANDLE hTitleKey; 02238 NTSTATUS Status; 02239 LPWSTR TranslatedConsoleTitle; 02240 DWORD dwValue; 02241 DWORD i; 02242 WCHAR awchFaceName[LF_FACESIZE]; 02243 WCHAR awchBuffer[64]; 02244 KEY_BASIC_INFORMATION KeyInfo; 02245 ULONG ResultLength; 02246 02247 // 02248 // Impersonate the client process 02249 // 02250 02251 if (!CsrImpersonateClient(NULL)) { 02252 KdPrint(("CONSRV: GetRegistryValues Impersonate failed\n")); 02253 return; 02254 } 02255 02256 // 02257 // Open the current user registry key 02258 // 02259 02260 Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey); 02261 if (!NT_SUCCESS(Status)) { 02262 CsrRevertToSelf(); 02263 return; 02264 } 02265 02266 // 02267 // Open the console registry key 02268 // 02269 02270 Status = MyRegOpenKey(hCurrentUserKey, 02271 CONSOLE_REGISTRY_STRING, 02272 &hConsoleKey); 02273 if (!NT_SUCCESS(Status)) { 02274 NtClose(hCurrentUserKey); 02275 CsrRevertToSelf(); 02276 return; 02277 } 02278 02279 // 02280 // If we're not reading the default key, check if the default values 02281 // need to be updated 02282 // 02283 02284 Status = NtQueryKey(hConsoleKey, 02285 KeyBasicInformation, 02286 &KeyInfo, 02287 sizeof(KeyInfo), 02288 &ResultLength); 02289 if (!NT_ERROR(Status)) { 02290 if (DefaultRegInfo.LastWriteTime != KeyInfo.LastWriteTime.QuadPart) { 02291 DefaultRegInfo.LastWriteTime = KeyInfo.LastWriteTime.QuadPart; 02292 if (RegInfo != &DefaultRegInfo) { 02293 GetRegistryValues(L"", &DefaultRegInfo); 02294 *RegInfo = DefaultRegInfo; 02295 } 02296 } 02297 } 02298 02299 // 02300 // Open the console title subkey 02301 // 02302 02303 TranslatedConsoleTitle = TranslateConsoleTitle(ConsoleTitle, NULL, TRUE, TRUE); 02304 if (TranslatedConsoleTitle == NULL) { 02305 NtClose(hConsoleKey); 02306 NtClose(hCurrentUserKey); 02307 CsrRevertToSelf(); 02308 return; 02309 } 02310 Status = MyRegOpenKey(hConsoleKey, 02311 TranslatedConsoleTitle, 02312 &hTitleKey); 02313 ConsoleHeapFree(TranslatedConsoleTitle); 02314 if (!NT_SUCCESS(Status)) { 02315 TranslatedConsoleTitle = TranslateConsoleTitle(ConsoleTitle, NULL, FALSE, TRUE); 02316 if (TranslatedConsoleTitle) { 02317 Status = MyRegOpenKey(hConsoleKey, 02318 TranslatedConsoleTitle, 02319 &hTitleKey); 02320 ConsoleHeapFree(TranslatedConsoleTitle); 02321 } 02322 } 02323 if (!NT_SUCCESS(Status)) { 02324 NtClose(hConsoleKey); 02325 NtClose(hCurrentUserKey); 02326 CsrRevertToSelf(); 02327 return; 02328 } 02329 02330 // 02331 // Initial screen fill 02332 // 02333 02334 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02335 CONSOLE_REGISTRY_FILLATTR, 02336 sizeof(dwValue), (PBYTE)&dwValue))) { 02337 RegInfo->ScreenFill.Attributes = (WORD)dwValue; 02338 } 02339 02340 // 02341 // Initial popup fill 02342 // 02343 02344 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02345 CONSOLE_REGISTRY_POPUPATTR, 02346 sizeof(dwValue), (PBYTE)&dwValue))) { 02347 RegInfo->PopupFill.Attributes = (WORD)dwValue; 02348 } 02349 02350 // 02351 // Initial insert mode 02352 // 02353 02354 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02355 CONSOLE_REGISTRY_INSERTMODE, 02356 sizeof(dwValue), (PBYTE)&dwValue))) { 02357 RegInfo->InsertMode = !!dwValue; 02358 } 02359 02360 // 02361 // Initial quick edit mode 02362 // 02363 02364 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02365 CONSOLE_REGISTRY_QUICKEDIT, 02366 sizeof(dwValue), (PBYTE)&dwValue))) { 02367 RegInfo->QuickEdit = !!dwValue; 02368 } 02369 02370 #ifdef i386 02371 // 02372 // Initial full screen mode 02373 // 02374 02375 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02376 CONSOLE_REGISTRY_FULLSCR, 02377 sizeof(dwValue), (PBYTE)&dwValue))) { 02378 RegInfo->FullScreen = !!dwValue; 02379 } 02380 #endif 02381 02382 #if defined(FE_SB) // scotthsu 02383 // 02384 // Code Page 02385 // 02386 02387 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02388 CONSOLE_REGISTRY_CODEPAGE, 02389 sizeof(dwValue), (PBYTE)&dwValue))) { 02390 RegInfo->CodePage = (UINT)dwValue; 02391 02392 // If this routine specified default settings for console property, 02393 // then make sure code page value when Fae East environment. 02394 // If code page value does not the same to OEMCP and any FE's code page then 02395 // we are override code page value to OEMCP on default console property. 02396 // Because, Far East environment has limitation that doesn not switch to 02397 // another FE's code page by the SetConsoleCP/SetConsoleOutputCP. 02398 // 02399 // Compare of ConsoleTitle and L"" has limit to default property of console. 02400 // It means, this code doesn't care user defined property. 02401 // Content of user defined property has responsibility to themselves. 02402 02403 if ( wcscmp(ConsoleTitle,L"") == 0 && 02404 IsAvailableFarEastCodePage( RegInfo->CodePage ) && 02405 OEMCP != RegInfo->CodePage ) { 02406 RegInfo->CodePage = OEMCP; 02407 } 02408 } 02409 #endif 02410 02411 // 02412 // Initial screen buffer size 02413 // 02414 02415 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02416 CONSOLE_REGISTRY_BUFFERSIZE, 02417 sizeof(dwValue), (PBYTE)&dwValue))) { 02418 RegInfo->ScreenBufferSize.X = LOWORD(dwValue); 02419 RegInfo->ScreenBufferSize.Y = HIWORD(dwValue); 02420 if (RegInfo->ScreenBufferSize.X <= 0) 02421 RegInfo->ScreenBufferSize.X = 1; 02422 if (RegInfo->ScreenBufferSize.Y <= 0) 02423 RegInfo->ScreenBufferSize.Y = 1; 02424 } 02425 02426 // 02427 // Initial window size 02428 // 02429 02430 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02431 CONSOLE_REGISTRY_WINDOWSIZE, 02432 sizeof(dwValue), (PBYTE)&dwValue))) { 02433 RegInfo->WindowSize.X = LOWORD(dwValue); 02434 RegInfo->WindowSize.Y = HIWORD(dwValue); 02435 if (RegInfo->WindowSize.X <= 0) 02436 RegInfo->WindowSize.X = 1; 02437 else if (RegInfo->WindowSize.X > RegInfo->ScreenBufferSize.X) 02438 RegInfo->WindowSize.X = RegInfo->ScreenBufferSize.X; 02439 if (RegInfo->WindowSize.Y <= 0) 02440 RegInfo->WindowSize.Y = 1; 02441 else if (RegInfo->WindowSize.Y > RegInfo->ScreenBufferSize.Y) 02442 RegInfo->WindowSize.Y = RegInfo->ScreenBufferSize.Y; 02443 } 02444 02445 // 02446 // Initial window position 02447 // 02448 02449 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02450 CONSOLE_REGISTRY_WINDOWPOS, 02451 sizeof(dwValue), (PBYTE)&dwValue))) { 02452 RegInfo->WindowOrigin.X = LOWORD(dwValue); 02453 RegInfo->WindowOrigin.Y = HIWORD(dwValue); 02454 RegInfo->AutoPosition = FALSE; 02455 } 02456 02457 // 02458 // Initial font size 02459 // 02460 02461 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02462 CONSOLE_REGISTRY_FONTSIZE, 02463 sizeof(dwValue), (PBYTE)&dwValue))) { 02464 RegInfo->FontSize.X = LOWORD(dwValue); 02465 RegInfo->FontSize.Y = HIWORD(dwValue); 02466 } 02467 02468 // 02469 // Initial font family 02470 // 02471 02472 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02473 CONSOLE_REGISTRY_FONTFAMILY, 02474 sizeof(dwValue), (PBYTE)&dwValue))) { 02475 RegInfo->FontFamily = dwValue; 02476 } 02477 02478 // 02479 // Initial font weight 02480 // 02481 02482 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02483 CONSOLE_REGISTRY_FONTWEIGHT, 02484 sizeof(dwValue), (PBYTE)&dwValue))) { 02485 RegInfo->FontWeight = dwValue; 02486 } 02487 02488 // 02489 // Initial font face name 02490 // 02491 02492 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02493 CONSOLE_REGISTRY_FACENAME, 02494 sizeof(awchFaceName), (PBYTE)awchFaceName))) { 02495 RtlCopyMemory(RegInfo->FaceName, awchFaceName, sizeof(awchFaceName)); 02496 RegInfo->FaceName[NELEM(RegInfo->FaceName) - 1] = 0; 02497 } 02498 02499 // 02500 // Initial cursor size 02501 // 02502 02503 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02504 CONSOLE_REGISTRY_CURSORSIZE, 02505 sizeof(dwValue), (PBYTE)&dwValue))) { 02506 RegInfo->CursorSize = dwValue; 02507 } 02508 02509 // 02510 // Initial history buffer size 02511 // 02512 02513 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02514 CONSOLE_REGISTRY_HISTORYSIZE, 02515 sizeof(dwValue), (PBYTE)&dwValue))) { 02516 RegInfo->HistoryBufferSize = dwValue; 02517 } 02518 02519 // 02520 // Initial number of history buffers 02521 // 02522 02523 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02524 CONSOLE_REGISTRY_HISTORYBUFS, 02525 sizeof(dwValue), (PBYTE)&dwValue))) { 02526 RegInfo->NumberOfHistoryBuffers = dwValue; 02527 } 02528 02529 // 02530 // Initial history duplication mode 02531 // 02532 02533 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02534 CONSOLE_REGISTRY_HISTORYNODUP, 02535 sizeof(dwValue), (PBYTE)&dwValue))) { 02536 RegInfo->HistoryNoDup = dwValue; 02537 } 02538 02539 for (i=0; i<16; i++) { 02540 wsprintf(awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i); 02541 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, awchBuffer, 02542 sizeof(dwValue), (PBYTE)&dwValue))) { 02543 RegInfo->ColorTable[ i ] = dwValue; 02544 } 02545 } 02546 02547 if (RegInfo == &DefaultRegInfo) { 02548 // 02549 // If the common (default) setting has been changed, 02550 // 02551 02552 // 02553 // Get registry for conime flag 02554 // 02555 if (NT_SUCCESS(MyRegQueryValue(hConsoleKey, CONSOLE_REGISTRY_LOAD_CONIME, sizeof dwValue, (PBYTE)&dwValue))) { 02556 gfLoadConIme = (dwValue != 0); 02557 } else { 02558 gfLoadConIme = TRUE; 02559 } 02560 02561 // 02562 // get extended edit mode and keys from registry. 02563 // 02564 if (NT_SUCCESS(MyRegQueryValue(hConsoleKey, 02565 CONSOLE_REGISTRY_EXTENDEDEDITKEY, 02566 sizeof dwValue, 02567 (PBYTE)&dwValue)) && 02568 dwValue <= 1) { 02569 02570 ExtKeyDefBuf buf; 02571 02572 gExtendedEditKey = dwValue; 02573 02574 // 02575 // Initialize Extended Edit keys 02576 // 02577 InitExtendedEditKeys(NULL); 02578 02579 if (NT_SUCCESS(MyRegQueryValue(hConsoleKey, 02580 CONSOLE_REGISTRY_EXTENDEDEDITKEY_CUSTOM, 02581 sizeof buf, 02582 (PBYTE)&buf))) { 02583 InitExtendedEditKeys(&buf); 02584 } 02585 #if DBG 02586 else { 02587 DbgPrint("Error reading ExtendedEditkeyCustom.\n"); 02588 } 02589 #endif 02590 } 02591 else { 02592 gExtendedEditKey = 0; 02593 DBGPRINT(("Error reading ExtendedEditkey.\n")); 02594 } 02595 02596 // 02597 // Word delimiters 02598 // 02599 if (gExtendedEditKey) { 02600 // If extended edit key is given, provide extended word delimiters 02601 // by default. 02602 memcpy((LPBYTE)gaWordDelimChars, (LPBYTE)gaWordDelimCharsDefault, 02603 sizeof gaWordDelimChars[0] * WORD_DELIM_MAX); 02604 } else { 02605 // Otherwise, stick to the original word delimiter. 02606 gaWordDelimChars[0] = L'\0'; 02607 } 02608 02609 // Read word delimiters from registry 02610 if (NT_SUCCESS(MyRegQueryValue(hConsoleKey, 02611 CONSOLE_REGISTRY_WORD_DELIM, 02612 sizeof awchBuffer, 02613 (PBYTE)awchBuffer))) { 02614 // OK, copy it to the word delimiter array. 02615 wcsncpy(gaWordDelimChars, awchBuffer, WORD_DELIM_MAX); 02616 gaWordDelimChars[WORD_DELIM_MAX - 1] = 0; 02617 } 02618 02619 // 02620 // Read Trim Zero Heading flag 02621 // 02622 if (NT_SUCCESS(MyRegQueryValue(hTitleKey, 02623 CONSOLE_REGISTRY_TRIMZEROHEADINGS, 02624 sizeof(dwValue), (PBYTE)&dwValue))) { 02625 gfTrimLeadingZeros = dwValue; 02626 } else { 02627 gfTrimLeadingZeros = FALSE; 02628 } 02629 } 02630 02631 02632 // 02633 // Close the registry keys 02634 // 02635 02636 NtClose(hTitleKey); 02637 NtClose(hConsoleKey); 02638 NtClose(hCurrentUserKey); 02639 CsrRevertToSelf(); 02640 } 02641 02642 NTSTATUS 02643 GetConsoleLangId( 02644 IN UINT OutputCP, 02645 OUT LANGID* pLangId 02646 ) 02647 { 02648 NTSTATUS Status; 02649 02650 if (CONSOLE_IS_DBCS_ENABLED()){ 02651 if (pLangId != NULL) { 02652 switch (OutputCP) { 02653 case 932: 02654 *pLangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT ); 02655 break; 02656 case 949: 02657 *pLangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN ); 02658 break; 02659 case 936: 02660 *pLangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); 02661 break; 02662 case 950: 02663 *pLangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ); 02664 break; 02665 default: 02666 *pLangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); 02667 break; 02668 } 02669 } 02670 Status = STATUS_SUCCESS; 02671 } 02672 else { 02673 Status = STATUS_NOT_SUPPORTED; 02674 } 02675 02676 return Status; 02677 } 02678 02679 ULONG 02680 SrvGetConsoleLangId( 02681 IN OUT PCSR_API_MSG m, 02682 IN OUT PCSR_REPLY_STATUS ReplyStatus 02683 ) 02684 { 02685 PCONSOLE_LANGID_MSG a = (PCONSOLE_LANGID_MSG)&m->u.ApiMessageData; 02686 NTSTATUS Status; 02687 PCONSOLE_INFORMATION Console; 02688 02689 Status = ApiPreamble(a->ConsoleHandle, 02690 &Console 02691 ); 02692 if (!NT_SUCCESS(Status)) { 02693 return Status; 02694 } 02695 Status = GetConsoleLangId(Console->OutputCP, &a->LangId); 02696 02697 UnlockConsole(Console); 02698 return((ULONG) Status); 02699 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 02700 }

Generated on Sat May 15 19:41:51 2004 for test by doxygen 1.3.7