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

handle.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 handle.c 00008 00009 Abstract: 00010 00011 This file manages console and io handles. 00012 00013 Author: 00014 00015 Therese Stowell (thereses) 16-Nov-1990 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "precomp.h" 00022 #pragma hdrstop 00023 00024 // 00025 // array of pointers to consoles 00026 // 00027 00028 PCONSOLE_INFORMATION InitialConsoleHandles[CONSOLE_INITIAL_CONSOLES]; 00029 PCONSOLE_INFORMATION *ConsoleHandles; 00030 ULONG NumberOfConsoleHandles; 00031 00032 CRITICAL_SECTION ConsoleHandleLock; // serializes console handle table access 00033 00034 ULONG ConsoleId=47; // unique number identifying console 00035 00036 // 00037 // Macros to manipulate console handles 00038 // 00039 00040 #define HandleFromIndex(i) ((HANDLE)((i & 0xFFFF) | (ConsoleId++ << 16))) 00041 #define IndexFromHandle(h) ((USHORT)((ULONG_PTR)h & 0xFFFF)) 00042 #define ConsoleHandleTableLocked() (ConsoleHandleLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread) 00043 00044 VOID 00045 AddProcessToList( 00046 IN OUT PCONSOLE_INFORMATION Console, 00047 IN OUT PCONSOLE_PROCESS_HANDLE ProcessHandleRecord, 00048 IN HANDLE ProcessHandle 00049 ); 00050 00051 VOID 00052 FreeInputHandle( 00053 IN PHANDLE_DATA HandleData 00054 ); 00055 00056 NTSTATUS 00057 InitializeConsoleHandleTable( VOID ) 00058 00059 /*++ 00060 00061 Routine Description: 00062 00063 This routine initializes the global console handle table. 00064 00065 Arguments: 00066 00067 none. 00068 00069 Return Value: 00070 00071 none. 00072 00073 --*/ 00074 00075 { 00076 NTSTATUS Status; 00077 00078 Status = RtlInitializeCriticalSectionAndSpinCount(&ConsoleHandleLock, 00079 0x80000000); 00080 00081 RtlZeroMemory(InitialConsoleHandles, sizeof(InitialConsoleHandles)); 00082 ConsoleHandles = InitialConsoleHandles; 00083 NumberOfConsoleHandles = NELEM(InitialConsoleHandles); 00084 00085 return Status; 00086 } 00087 00088 00089 #ifdef DEBUG 00090 00091 VOID 00092 LockConsoleHandleTable( VOID ) 00093 00094 /*++ 00095 00096 Routine Description: 00097 00098 This routine locks the global console handle table. It also verifies 00099 that we're not in the USER critical section. This is necessary to 00100 prevent potential deadlocks. This routine is only defined in debug 00101 builds. 00102 00103 Arguments: 00104 00105 none. 00106 00107 Return Value: 00108 00109 none. 00110 00111 --*/ 00112 00113 { 00114 RtlEnterCriticalSection(&ConsoleHandleLock); 00115 } 00116 00117 00118 VOID 00119 UnlockConsoleHandleTable( VOID ) 00120 00121 /*++ 00122 00123 Routine Description: 00124 00125 This routine unlocks the global console handle table. This routine 00126 is only defined in debug builds. 00127 00128 Arguments: 00129 00130 none. 00131 00132 Return Value: 00133 00134 none. 00135 00136 --*/ 00137 00138 { 00139 RtlLeaveCriticalSection(&ConsoleHandleLock); 00140 } 00141 00142 00143 VOID 00144 LockConsole( 00145 IN PCONSOLE_INFORMATION Console 00146 ) 00147 00148 /*++ 00149 00150 Routine Description: 00151 00152 This routine locks the console.This routine is only defined 00153 in debug builds. 00154 00155 Arguments: 00156 00157 none. 00158 00159 Return Value: 00160 00161 none. 00162 00163 --*/ 00164 00165 { 00166 ASSERT(!ConsoleHandleTableLocked()); 00167 RtlEnterCriticalSection(&(Console->ConsoleLock)); 00168 ASSERT(ConsoleLocked(Console)); 00169 } 00170 00171 #endif // DEBUG 00172 00173 00174 NTSTATUS 00175 DereferenceConsoleHandle( 00176 IN HANDLE ConsoleHandle, 00177 OUT PCONSOLE_INFORMATION *Console 00178 ) 00179 00180 /*++ 00181 00182 Routine Description: 00183 00184 This routine converts a console handle value into a pointer to the 00185 console data structure. 00186 00187 Arguments: 00188 00189 ConsoleHandle - console handle to convert. 00190 00191 Console - On output, contains pointer to the console data structure. 00192 00193 Return Value: 00194 00195 none. 00196 00197 Note: 00198 00199 The console handle table lock must be held when calling this routine. 00200 00201 --*/ 00202 00203 { 00204 ULONG i; 00205 00206 ASSERT(ConsoleHandleTableLocked()); 00207 00208 i = IndexFromHandle(ConsoleHandle); 00209 if ((i >= NumberOfConsoleHandles) || 00210 ((*Console = ConsoleHandles[i]) == NULL) || 00211 ((*Console)->ConsoleHandle != ConsoleHandle)) { 00212 *Console = NULL; 00213 return STATUS_INVALID_HANDLE; 00214 } 00215 if ((*Console)->Flags & CONSOLE_TERMINATING) { 00216 *Console = NULL; 00217 return STATUS_PROCESS_IS_TERMINATING; 00218 } 00219 return STATUS_SUCCESS; 00220 } 00221 00222 NTSTATUS 00223 GrowConsoleHandleTable( VOID ) 00224 00225 /*++ 00226 00227 Routine Description: 00228 00229 This routine grows the console handle table. 00230 00231 Arguments: 00232 00233 none 00234 00235 Return Value: 00236 00237 --*/ 00238 00239 { 00240 PCONSOLE_INFORMATION *NewTable; 00241 PCONSOLE_INFORMATION *OldTable; 00242 ULONG i; 00243 ULONG MaxConsoleHandles; 00244 00245 ASSERT(ConsoleHandleTableLocked()); 00246 00247 MaxConsoleHandles = NumberOfConsoleHandles + CONSOLE_CONSOLE_HANDLE_INCREMENT; 00248 ASSERT(MaxConsoleHandles <= 0xFFFF); 00249 NewTable = (PCONSOLE_INFORMATION *)ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),MaxConsoleHandles * sizeof(PCONSOLE_INFORMATION)); 00250 if (NewTable == NULL) { 00251 return STATUS_NO_MEMORY; 00252 } 00253 RtlCopyMemory(NewTable, ConsoleHandles, 00254 NumberOfConsoleHandles * sizeof(PCONSOLE_INFORMATION)); 00255 for (i=NumberOfConsoleHandles;i<MaxConsoleHandles;i++) { 00256 NewTable[i] = NULL; 00257 } 00258 OldTable = ConsoleHandles; 00259 ConsoleHandles = NewTable; 00260 NumberOfConsoleHandles = MaxConsoleHandles; 00261 if (OldTable != InitialConsoleHandles) { 00262 ConsoleHeapFree(OldTable); 00263 } 00264 return STATUS_SUCCESS; 00265 } 00266 00267 00268 NTSTATUS 00269 AllocateConsoleHandle( 00270 OUT PHANDLE Handle 00271 ) 00272 00273 /*++ 00274 00275 Routine Description: 00276 00277 This routine allocates a console handle from the global table. 00278 00279 Arguments: 00280 00281 Handle - Pointer to store handle in. 00282 00283 Return Value: 00284 00285 Note: 00286 00287 The console handle table lock must be held when calling this routine. 00288 00289 --*/ 00290 00291 { 00292 ULONG i; 00293 NTSTATUS Status; 00294 00295 ASSERT(ConsoleHandleTableLocked()); 00296 00297 // 00298 // have to start allocation at 1 because 0 indicates no console handle 00299 // in ConDllInitialize. 00300 // 00301 00302 for (i=1;i<NumberOfConsoleHandles;i++) { 00303 if (ConsoleHandles[i] == NULL) { 00304 ConsoleHandles[i] = (PCONSOLE_INFORMATION) CONSOLE_HANDLE_ALLOCATED; 00305 *Handle = HandleFromIndex(i); 00306 return STATUS_SUCCESS; 00307 } 00308 } 00309 00310 // 00311 // grow console handle table 00312 // 00313 00314 Status = GrowConsoleHandleTable(); 00315 if (!NT_SUCCESS(Status)) 00316 return Status; 00317 for ( ;i<NumberOfConsoleHandles;i++) { 00318 if (ConsoleHandles[i] == NULL) { 00319 ConsoleHandles[i] = (PCONSOLE_INFORMATION) CONSOLE_HANDLE_ALLOCATED; 00320 *Handle = HandleFromIndex(i); 00321 return STATUS_SUCCESS; 00322 } 00323 } 00324 ASSERT (FALSE); 00325 return STATUS_UNSUCCESSFUL; 00326 } 00327 00328 00329 00330 NTSTATUS 00331 FreeConsoleHandle( 00332 IN HANDLE Handle 00333 ) 00334 00335 /*++ 00336 00337 Routine Description: 00338 00339 This routine frees a console handle from the global table. 00340 00341 Arguments: 00342 00343 Handle - Handle to free. 00344 00345 Return Value: 00346 00347 Note: 00348 00349 The console handle table lock must be held when calling this routine. 00350 00351 --*/ 00352 00353 { 00354 ULONG i; 00355 00356 ASSERT(ConsoleHandleTableLocked()); 00357 00358 ASSERT (Handle != NULL); 00359 i = IndexFromHandle(Handle); 00360 if ((i >= NumberOfConsoleHandles) || (ConsoleHandles[i] == NULL)) { 00361 ASSERT (FALSE); 00362 } else { 00363 ConsoleHandles[i] = NULL; 00364 } 00365 return STATUS_SUCCESS; 00366 } 00367 00368 00369 NTSTATUS 00370 ValidateConsole( 00371 IN PCONSOLE_INFORMATION Console 00372 ) 00373 00374 /*++ 00375 00376 Routine Description: 00377 00378 This routine ensures that the given console pointer is valid. 00379 00380 Arguments: 00381 00382 Console - Console pointer to validate. 00383 00384 --*/ 00385 00386 { 00387 ULONG i; 00388 00389 if (Console != NULL) { 00390 for (i = 0; i < NumberOfConsoleHandles; i++) { 00391 if (ConsoleHandles[i] == Console) 00392 return STATUS_SUCCESS; 00393 } 00394 } 00395 return STATUS_UNSUCCESSFUL; 00396 } 00397 00398 00399 NTSTATUS 00400 InitializeIoHandleTable( 00401 IN OUT PCONSOLE_INFORMATION Console, 00402 OUT PCONSOLE_PER_PROCESS_DATA ProcessData, 00403 OUT PHANDLE StdIn, 00404 OUT PHANDLE StdOut, 00405 OUT PHANDLE StdErr 00406 ) 00407 00408 /*++ 00409 00410 Routine Description: 00411 00412 This routine initializes a process's handle table for the first 00413 time (there is no parent process). It also sets up stdin, stdout, 00414 and stderr. 00415 00416 Arguments: 00417 00418 Console - Pointer to console information structure. 00419 00420 ProcessData - Pointer to per process data structure. 00421 00422 Stdin - Pointer in which to return StdIn handle. 00423 00424 StdOut - Pointer in which to return StdOut handle. 00425 00426 StdErr - Pointer in which to return StdErr handle. 00427 00428 Return Value: 00429 00430 --*/ 00431 00432 { 00433 ULONG i; 00434 HANDLE Handle; 00435 NTSTATUS Status; 00436 PHANDLE_DATA HandleData; 00437 00438 // HandleTablePtr gets set up by ConsoleAddProcessRoutine. 00439 // it will be != to HandleTable if the new process was created 00440 // using "start xxx" at the command line and cmd.exe has > 00441 // CONSOLE_INITIAL_IO_HANDLES. 00442 00443 if (ProcessData->HandleTablePtr != ProcessData->HandleTable) { 00444 ASSERT(ProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES); 00445 ConsoleHeapFree(ProcessData->HandleTablePtr); 00446 ProcessData->HandleTablePtr = ProcessData->HandleTable; 00447 } 00448 00449 for (i=0;i<CONSOLE_INITIAL_IO_HANDLES;i++) { 00450 ProcessData->HandleTable[i].HandleType = CONSOLE_FREE_HANDLE; 00451 } 00452 00453 ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES; 00454 ProcessData->Foo = 0xF00; 00455 00456 // 00457 // set up stdin, stdout, stderr. we don't do any cleanup in case 00458 // of errors because we're going to fail the console creation. 00459 // 00460 // stdin 00461 // 00462 00463 Status = AllocateIoHandle(ProcessData, 00464 CONSOLE_INPUT_HANDLE, 00465 &Handle 00466 ); 00467 if (!NT_SUCCESS(Status)) { 00468 return((ULONG) Status); 00469 } 00470 Status = DereferenceIoHandleNoCheck(ProcessData, 00471 Handle, 00472 &HandleData 00473 ); 00474 ASSERT (NT_SUCCESS(Status)); 00475 if (!NT_SUCCESS(Status)) { 00476 return((ULONG) Status); 00477 } 00478 if (!InitializeInputHandle(HandleData, 00479 &Console->InputBuffer)) { 00480 return STATUS_NO_MEMORY; 00481 } 00482 HandleData->HandleType |= CONSOLE_INHERITABLE; 00483 Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE, 00484 FILE_SHARE_READ | FILE_SHARE_WRITE, 00485 &Console->InputBuffer.ShareAccess, 00486 HandleData 00487 ); 00488 ASSERT(NT_SUCCESS(Status)); 00489 if (!NT_SUCCESS(Status)) { 00490 return((ULONG) Status); 00491 } 00492 *StdIn = INDEX_TO_HANDLE(Handle); 00493 00494 // 00495 // stdout 00496 // 00497 00498 Status = AllocateIoHandle(ProcessData, 00499 CONSOLE_OUTPUT_HANDLE, 00500 &Handle 00501 ); 00502 if (!NT_SUCCESS(Status)) { 00503 return((ULONG) Status); 00504 } 00505 Status = DereferenceIoHandleNoCheck(ProcessData, 00506 Handle, 00507 &HandleData 00508 ); 00509 ASSERT (NT_SUCCESS(Status)); 00510 if (!NT_SUCCESS(Status)) { 00511 return((ULONG) Status); 00512 } 00513 InitializeOutputHandle(HandleData,Console->CurrentScreenBuffer); 00514 HandleData->HandleType |= CONSOLE_INHERITABLE; 00515 Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE, 00516 FILE_SHARE_READ | FILE_SHARE_WRITE, 00517 &Console->ScreenBuffers->ShareAccess, 00518 HandleData 00519 ); 00520 ASSERT(NT_SUCCESS(Status)); 00521 if (!NT_SUCCESS(Status)) { 00522 return((ULONG) Status); 00523 } 00524 *StdOut = INDEX_TO_HANDLE(Handle); 00525 00526 // 00527 // stderr 00528 // 00529 00530 Status = AllocateIoHandle(ProcessData, 00531 CONSOLE_OUTPUT_HANDLE, 00532 &Handle 00533 ); 00534 if (!NT_SUCCESS(Status)) { 00535 return((ULONG) Status); 00536 } 00537 Status = DereferenceIoHandleNoCheck(ProcessData, 00538 Handle, 00539 &HandleData 00540 ); 00541 ASSERT (NT_SUCCESS(Status)); 00542 if (!NT_SUCCESS(Status)) { 00543 return((ULONG) Status); 00544 } 00545 InitializeOutputHandle(HandleData,Console->CurrentScreenBuffer); 00546 HandleData->HandleType |= CONSOLE_INHERITABLE; 00547 Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE, 00548 FILE_SHARE_READ | FILE_SHARE_WRITE, 00549 &Console->ScreenBuffers->ShareAccess, 00550 HandleData 00551 ); 00552 ASSERT(NT_SUCCESS(Status)); 00553 if (!NT_SUCCESS(Status)) { 00554 return((ULONG) Status); 00555 } 00556 *StdErr = INDEX_TO_HANDLE(Handle); 00557 return STATUS_SUCCESS; 00558 } 00559 00560 NTSTATUS 00561 InheritIoHandleTable( 00562 IN PCONSOLE_INFORMATION Console, 00563 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 00564 IN PCONSOLE_PER_PROCESS_DATA ParentProcessData 00565 ) 00566 00567 /*++ 00568 00569 Routine Description: 00570 00571 This routine creates a process's handle table from the parent 00572 process's handle table. ProcessData contains the process data 00573 copied directly from the parent to the child process by CSR. 00574 This routine allocates a new handle table, if necessary, then 00575 invalidates non-inherited handles and increments the sharing 00576 and reference counts for inherited handles. 00577 00578 Arguments: 00579 00580 ProcessData - Pointer to per process data structure. 00581 00582 Return Value: 00583 00584 Note: 00585 00586 The console lock must be held when calling this routine. 00587 00588 --*/ 00589 00590 { 00591 ULONG i; 00592 NTSTATUS Status; 00593 00594 // 00595 // Copy handles from parent process. If the table size 00596 // is CONSOLE_INITIAL_IO_HANDLES, CSR has done the copy 00597 // for us. 00598 // 00599 00600 UNREFERENCED_PARAMETER(Console); 00601 00602 ASSERT(ParentProcessData->Foo == 0xF00); 00603 ASSERT(ParentProcessData->HandleTableSize != 0); 00604 ASSERT(ParentProcessData->HandleTableSize <= 0x0000FFFF); 00605 00606 if (ParentProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES) { 00607 ProcessData->HandleTableSize = ParentProcessData->HandleTableSize; 00608 ProcessData->HandleTablePtr = (PHANDLE_DATA)ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),ProcessData->HandleTableSize * sizeof(HANDLE_DATA)); 00609 00610 if (ProcessData->HandleTablePtr == NULL) { 00611 ProcessData->HandleTablePtr = ProcessData->HandleTable; 00612 ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES; 00613 return STATUS_NO_MEMORY; 00614 } 00615 RtlCopyMemory(ProcessData->HandleTablePtr, 00616 ParentProcessData->HandleTablePtr, 00617 ProcessData->HandleTableSize * sizeof(HANDLE_DATA)); 00618 } 00619 00620 ASSERT(!(Console->Flags & CONSOLE_SHUTTING_DOWN)); 00621 00622 // 00623 // Allocate any memory associated with each handle. 00624 // 00625 00626 Status = STATUS_SUCCESS; 00627 for (i=0;i<ProcessData->HandleTableSize;i++) { 00628 00629 if (NT_SUCCESS(Status) && ProcessData->HandleTablePtr[i].HandleType & CONSOLE_INHERITABLE) { 00630 00631 if (ProcessData->HandleTablePtr[i].HandleType & CONSOLE_INPUT_HANDLE) { 00632 ProcessData->HandleTablePtr[i].InputReadData = (PINPUT_READ_HANDLE_DATA)ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),sizeof(INPUT_READ_HANDLE_DATA)); 00633 if (!ProcessData->HandleTablePtr[i].InputReadData) { 00634 ProcessData->HandleTablePtr[i].HandleType = CONSOLE_FREE_HANDLE; 00635 Status = STATUS_NO_MEMORY; 00636 continue; 00637 } 00638 ProcessData->HandleTablePtr[i].InputReadData->InputHandleFlags = 0; 00639 ProcessData->HandleTablePtr[i].InputReadData->ReadCount = 0; 00640 Status = RtlInitializeCriticalSection(&ProcessData->HandleTablePtr[i].InputReadData->ReadCountLock); 00641 if (!NT_SUCCESS(Status)) { 00642 ConsoleHeapFree(ProcessData->HandleTablePtr[i].InputReadData); 00643 ProcessData->HandleTablePtr[i].InputReadData = NULL; 00644 ProcessData->HandleTablePtr[i].HandleType = CONSOLE_FREE_HANDLE; 00645 continue; 00646 } 00647 } 00648 } 00649 else { 00650 ProcessData->HandleTablePtr[i].HandleType = CONSOLE_FREE_HANDLE; 00651 } 00652 } 00653 00654 // 00655 // If something failed, we need to free any input data we allocated and 00656 // free the handle table. 00657 // 00658 00659 if (!NT_SUCCESS(Status)) { 00660 for (i=0;i<ProcessData->HandleTableSize;i++) { 00661 if (ProcessData->HandleTablePtr[i].HandleType & CONSOLE_INPUT_HANDLE) { 00662 FreeInputHandle(&ProcessData->HandleTablePtr[i]); 00663 } 00664 } 00665 if (ProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES) { 00666 ConsoleHeapFree(ProcessData->HandleTablePtr); 00667 ProcessData->HandleTablePtr = ProcessData->HandleTable; 00668 ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES; 00669 } 00670 return Status; 00671 } 00672 00673 // 00674 // All the memory allocations succeeded. Now go through and increment the 00675 // object reference counts and dup the shares. 00676 // 00677 00678 for (i=0;i<ProcessData->HandleTableSize;i++) { 00679 if (ProcessData->HandleTablePtr[i].HandleType != CONSOLE_FREE_HANDLE) { 00680 PCONSOLE_SHARE_ACCESS ShareAccess; 00681 00682 if (ProcessData->HandleTablePtr[i].HandleType & CONSOLE_INPUT_HANDLE) { 00683 ProcessData->HandleTablePtr[i].Buffer.InputBuffer->RefCount++; 00684 ShareAccess = &ProcessData->HandleTablePtr[i].Buffer.InputBuffer->ShareAccess; 00685 } 00686 else { 00687 ProcessData->HandleTablePtr[i].Buffer.ScreenBuffer->RefCount++; 00688 ShareAccess = &ProcessData->HandleTablePtr[i].Buffer.ScreenBuffer->ShareAccess; 00689 } 00690 00691 Status = ConsoleDupShare(ProcessData->HandleTablePtr[i].Access, 00692 ProcessData->HandleTablePtr[i].ShareAccess, 00693 ShareAccess, 00694 &ProcessData->HandleTablePtr[i] 00695 ); 00696 ASSERT (NT_SUCCESS(Status)); 00697 } 00698 } 00699 ASSERT(ProcessData->Foo == 0xF00); 00700 00701 return STATUS_SUCCESS; 00702 } 00703 00704 NTSTATUS 00705 ConsoleAddProcessRoutine( 00706 IN PCSR_PROCESS ParentProcess, 00707 IN PCSR_PROCESS Process 00708 ) 00709 { 00710 PCONSOLE_PER_PROCESS_DATA ProcessData, ParentProcessData; 00711 PCONSOLE_INFORMATION Console; 00712 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 00713 NTSTATUS Status = STATUS_SUCCESS; 00714 ULONG i; 00715 00716 ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process); 00717 ProcessData->HandleTablePtr = ProcessData->HandleTable; 00718 ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES; 00719 CONSOLE_SETCONSOLEAPPFROMPROCESSDATA(ProcessData,FALSE); 00720 00721 if (ParentProcess) { 00722 00723 ProcessData->RootProcess = FALSE; 00724 ParentProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(ParentProcess); 00725 00726 // 00727 // If both the parent and new processes are console apps, 00728 // inherit handles from the parent process. 00729 // 00730 00731 if (ParentProcessData->ConsoleHandle != NULL && 00732 (Process->Flags & CSR_PROCESS_CONSOLEAPP)) { 00733 if (!(NT_SUCCESS(RevalidateConsole(ParentProcessData->ConsoleHandle, 00734 &Console)))) { 00735 ProcessData->ConsoleHandle = NULL; 00736 return STATUS_PROCESS_IS_TERMINATING; 00737 } 00738 00739 // 00740 // Don't add the process if the console is being shutdown. 00741 // 00742 00743 if (Console->Flags & CONSOLE_SHUTTING_DOWN) { 00744 Status = STATUS_PROCESS_IS_TERMINATING; 00745 } else { 00746 ProcessHandleRecord = ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),sizeof(CONSOLE_PROCESS_HANDLE)); 00747 if (ProcessHandleRecord == NULL) { 00748 Status = STATUS_NO_MEMORY; 00749 } else { 00750 00751 // 00752 // duplicate parent's handle table 00753 // 00754 00755 ASSERT(ProcessData->Foo == 0xF00); 00756 Status = InheritIoHandleTable(Console, ProcessData, ParentProcessData); 00757 if (NT_SUCCESS(Status)) { 00758 ProcessHandleRecord->Process = Process; 00759 ProcessHandleRecord->CtrlRoutine = NULL; 00760 ProcessHandleRecord->PropRoutine = NULL; 00761 AddProcessToList(Console,ProcessHandleRecord,Process->ProcessHandle); 00762 00763 // 00764 // increment console reference count 00765 // 00766 00767 Console->RefCount++; 00768 } else { 00769 ConsoleHeapFree(ProcessHandleRecord); 00770 } 00771 } 00772 } 00773 if (!NT_SUCCESS(Status)) { 00774 ProcessData->ConsoleHandle = NULL; 00775 for (i=0;i<CONSOLE_INITIAL_IO_HANDLES;i++) { 00776 ProcessData->HandleTable[i].HandleType = CONSOLE_FREE_HANDLE; 00777 } 00778 } 00779 UnlockConsole(Console); 00780 } else 00781 ProcessData->ConsoleHandle = NULL; 00782 } else { 00783 ProcessData->ConsoleHandle = NULL; 00784 } 00785 return Status; 00786 } 00787 00788 NTSTATUS 00789 AllocateConsole( 00790 IN HANDLE ConsoleHandle, 00791 IN LPWSTR Title, 00792 IN USHORT TitleLength, 00793 IN HANDLE ClientProcessHandle, 00794 OUT PHANDLE StdIn, 00795 OUT PHANDLE StdOut, 00796 OUT PHANDLE StdErr, 00797 OUT PCONSOLE_PER_PROCESS_DATA ProcessData, 00798 IN OUT PCONSOLE_INFO ConsoleInfo, 00799 IN BOOLEAN WindowVisible, 00800 IN DWORD dwConsoleThreadId 00801 ) 00802 00803 /*++ 00804 00805 Routine Description: 00806 00807 This routine allocates and initialized a console and its associated 00808 data - input buffer and screen buffer. 00809 00810 Arguments: 00811 00812 ConsoleHandle - Handle of console to allocate. 00813 00814 dwWindowSize - Initial size of screen buffer window, in rows and columns. 00815 00816 nFont - Initial number of font text is displayed in. 00817 00818 dwScreenBufferSize - Initial size of screen buffer, in rows and columns. 00819 00820 nInputBufferSize - Initial size of input buffer, in events. 00821 00822 dwWindowFlags - 00823 00824 StdIn - On return, contains handle to stdin. 00825 00826 StdOut - On return, contains handle to stdout. 00827 00828 StdErr - On return, contains handle to stderr. 00829 00830 ProcessData - On return, contains the initialized per-process data. 00831 00832 Return Value: 00833 00834 Note: 00835 00836 The console handle table lock must be held when calling this routine. 00837 00838 --*/ 00839 00840 { 00841 PCONSOLE_INFORMATION Console; 00842 NTSTATUS Status; 00843 BOOL Success; 00844 00845 // 00846 // allocate console data 00847 // 00848 00849 Console = (PCONSOLE_INFORMATION)ConsoleHeapAlloc( MAKE_TAG( CONSOLE_TAG ) | HEAP_ZERO_MEMORY, 00850 sizeof(CONSOLE_INFORMATION)); 00851 if (Console == NULL) { 00852 return STATUS_NO_MEMORY; 00853 } 00854 ConsoleHandles[IndexFromHandle(ConsoleHandle)] = Console; 00855 00856 Console->Flags = WindowVisible ? 0 : CONSOLE_NO_WINDOW; 00857 Console->hIcon = ConsoleInfo->hIcon; 00858 Console->hSmIcon = ConsoleInfo->hSmIcon; 00859 Console->iIconId = ConsoleInfo->iIconId; 00860 Console->dwHotKey = ConsoleInfo->dwHotKey; 00861 #if !defined(FE_SB) 00862 Console->CP = OEMCP; 00863 Console->OutputCP = ConsoleOutputCP; 00864 #endif 00865 Console->ReserveKeys = CONSOLE_NOSHORTCUTKEY; 00866 Console->ConsoleHandle = ConsoleHandle; 00867 Console->bIconInit = TRUE; 00868 Console->VerticalClientToWindow = VerticalClientToWindow; 00869 Console->HorizontalClientToWindow = HorizontalClientToWindow; 00870 #if defined(FE_SB) 00871 SetConsoleCPInfo(Console,TRUE); 00872 SetConsoleCPInfo(Console,FALSE); 00873 #endif 00874 00875 // 00876 // must wait for window to be destroyed or client impersonation won't 00877 // work. 00878 // 00879 00880 Status = NtDuplicateObject(NtCurrentProcess(), 00881 CONSOLE_CLIENTTHREADHANDLE(CSR_SERVER_QUERYCLIENTTHREAD()), 00882 NtCurrentProcess(), 00883 &Console->ClientThreadHandle, 00884 0, 00885 FALSE, 00886 DUPLICATE_SAME_ACCESS 00887 ); 00888 if (!NT_SUCCESS(Status)) { 00889 goto ErrorExit5; 00890 } 00891 00892 #if DBG 00893 // 00894 // Make sure the handle isn't protected so we can close it later 00895 // 00896 UnProtectHandle(Console->ClientThreadHandle); 00897 #endif // DBG 00898 00899 InitializeListHead(&Console->OutputQueue); 00900 InitializeListHead(&Console->ProcessHandleList); 00901 InitializeListHead(&Console->ExeAliasList); 00902 InitializeListHead(&Console->MessageQueue); 00903 00904 Status = NtCreateEvent(&Console->InitEvents[INITIALIZATION_SUCCEEDED], 00905 EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); 00906 if (!NT_SUCCESS(Status)) { 00907 goto ErrorExit4a; 00908 } 00909 Status = NtCreateEvent(&Console->InitEvents[INITIALIZATION_FAILED], 00910 EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); 00911 if (!NT_SUCCESS(Status)) { 00912 goto ErrorExit4; 00913 } 00914 Status = RtlInitializeCriticalSection(&Console->ConsoleLock); 00915 if (!NT_SUCCESS(Status)) { 00916 goto ErrorExit3a; 00917 } 00918 InitializeConsoleCommandData(Console); 00919 00920 // 00921 // initialize input buffer 00922 // 00923 00924 #if defined(FE_SB) 00925 Status = CreateInputBuffer(ConsoleInfo->nInputBufferSize, 00926 &Console->InputBuffer, 00927 Console); 00928 #else 00929 Status = CreateInputBuffer(ConsoleInfo->nInputBufferSize, 00930 &Console->InputBuffer); 00931 #endif 00932 if (!NT_SUCCESS(Status)) { 00933 goto ErrorExit3; 00934 } 00935 00936 Console->Title = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( TITLE_TAG ),TitleLength+sizeof(WCHAR)); 00937 if (Console->Title == NULL) { 00938 Status = STATUS_NO_MEMORY; 00939 goto ErrorExit2; 00940 } 00941 RtlCopyMemory(Console->Title,Title,TitleLength); 00942 Console->Title[TitleLength/sizeof(WCHAR)] = (WCHAR)0; // NULL terminate 00943 Console->TitleLength = TitleLength; 00944 00945 Console->OriginalTitle = TranslateConsoleTitle(Console->Title, &Console->OriginalTitleLength, TRUE, FALSE); 00946 if (Console->OriginalTitle == NULL) { 00947 Status = STATUS_NO_MEMORY; 00948 goto ErrorExit1; 00949 } 00950 00951 Status = NtCreateEvent(&Console->TerminationEvent, 00952 EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); 00953 if (!NT_SUCCESS(Status)) { 00954 goto ErrorExit1a; 00955 } 00956 00957 // 00958 // initialize screen buffer. we don't call OpenConsole to do this 00959 // because we need to specify the font, windowsize, etc. 00960 // 00961 00962 Status = DoCreateScreenBuffer(Console, 00963 ConsoleInfo); 00964 if (!NT_SUCCESS(Status)){ 00965 goto ErrorExit1b; 00966 } 00967 00968 00969 Console->CurrentScreenBuffer = Console->ScreenBuffers; 00970 #if defined(FE_SB) 00971 #if defined(FE_IME) 00972 SetUndetermineAttribute(Console) ; 00973 #endif 00974 Status = CreateEUDC(Console); 00975 if (!NT_SUCCESS(Status)){ 00976 goto ErrorExit1c; 00977 } 00978 #endif 00979 Status = InitializeIoHandleTable(Console, 00980 ProcessData, 00981 StdIn, 00982 StdOut, 00983 StdErr 00984 ); 00985 if (!NT_SUCCESS(Status)) { 00986 goto ErrorExit0; 00987 } 00988 00989 // 00990 // map event handles 00991 // 00992 00993 if (!MapHandle(ClientProcessHandle, 00994 Console->InitEvents[INITIALIZATION_SUCCEEDED], 00995 &ConsoleInfo->InitEvents[INITIALIZATION_SUCCEEDED] 00996 )) { 00997 Status = STATUS_NO_MEMORY; 00998 goto ErrorExit0; 00999 } 01000 if (!MapHandle(ClientProcessHandle, 01001 Console->InitEvents[INITIALIZATION_FAILED], 01002 &ConsoleInfo->InitEvents[INITIALIZATION_FAILED] 01003 )) { 01004 Status = STATUS_NO_MEMORY; 01005 goto ErrorExit0; 01006 } 01007 if (!MapHandle(ClientProcessHandle, 01008 Console->InputBuffer.InputWaitEvent, 01009 &ConsoleInfo->InputWaitHandle 01010 )) { 01011 Status = STATUS_NO_MEMORY; 01012 goto ErrorExit0; 01013 } 01014 01015 Success = PostThreadMessage(dwConsoleThreadId, 01016 CM_CREATE_CONSOLE_WINDOW, 01017 (WPARAM)ConsoleHandle, 01018 (LPARAM)ClientProcessHandle 01019 ); 01020 if (!Success) { 01021 KdPrint(("CONSRV: PostThreadMessage failed %d\n",GetLastError())); 01022 Status = STATUS_UNSUCCESSFUL; 01023 goto ErrorExit0; 01024 } 01025 01026 return STATUS_SUCCESS; 01027 01028 ErrorExit0: Console->ScreenBuffers->RefCount = 0; 01029 #if defined(FE_SB) 01030 if (Console->EudcInformation != NULL) { 01031 ConsoleHeapFree(Console->EudcInformation); 01032 } 01033 ErrorExit1c: 01034 #endif 01035 FreeScreenBuffer(Console->ScreenBuffers); 01036 ErrorExit1b: NtClose(Console->TerminationEvent); 01037 ErrorExit1a: ConsoleHeapFree(Console->OriginalTitle); 01038 ErrorExit1: ConsoleHeapFree(Console->Title); 01039 ErrorExit2: Console->InputBuffer.RefCount = 0; 01040 FreeInputBuffer(&Console->InputBuffer); 01041 ErrorExit3: RtlDeleteCriticalSection(&Console->ConsoleLock); 01042 01043 ErrorExit3a: NtClose(Console->InitEvents[INITIALIZATION_FAILED]); 01044 ErrorExit4: NtClose(Console->InitEvents[INITIALIZATION_SUCCEEDED]); 01045 ErrorExit4a: NtClose(Console->ClientThreadHandle); 01046 ErrorExit5: ConsoleHeapFree(Console); 01047 return Status; 01048 } 01049 01050 VOID 01051 DestroyConsole( 01052 IN PCONSOLE_INFORMATION Console 01053 ) 01054 01055 /*++ 01056 01057 Routine Description: 01058 01059 This routine frees a console structure if it's not being referenced. 01060 01061 Arguments: 01062 01063 Console - Console to free. 01064 01065 Return Value: 01066 01067 01068 --*/ 01069 01070 { 01071 HANDLE ConsoleHandle = Console->ConsoleHandle; 01072 01073 // 01074 // Make sure we have the console locked and it really is going away. 01075 // 01076 01077 ASSERT(ConsoleLocked(Console)); 01078 ASSERT(Console->hWnd == NULL); 01079 01080 // 01081 // Mark this console as being destroyed. 01082 // 01083 01084 Console->Flags |= CONSOLE_IN_DESTRUCTION; 01085 01086 // 01087 // Unlock this console. 01088 // 01089 01090 RtlLeaveCriticalSection(&Console->ConsoleLock); 01091 01092 // 01093 // If the console still exists and no one is waiting on it, free it. 01094 // 01095 01096 LockConsoleHandleTable(); 01097 if (Console == ConsoleHandles[IndexFromHandle(ConsoleHandle)] && 01098 Console->ConsoleHandle == ConsoleHandle && 01099 Console->ConsoleLock.OwningThread == NULL && 01100 Console->WaitCount == 0) { 01101 01102 FreeConsoleHandle(ConsoleHandle); 01103 RtlDeleteCriticalSection(&Console->ConsoleLock); 01104 ConsoleHeapFree(Console); 01105 } 01106 UnlockConsoleHandleTable(); 01107 } 01108 01109 VOID 01110 FreeCon( 01111 IN PCONSOLE_INFORMATION Console 01112 ) 01113 01114 /*++ 01115 01116 Routine Description: 01117 01118 This routine frees a console and its associated 01119 data - input buffer and screen buffer. 01120 01121 Arguments: 01122 01123 ConsoleHandle - Handle of console to free. 01124 01125 Return Value: 01126 01127 Note: 01128 01129 The console handle table lock must be held when calling this routine. 01130 01131 --*/ 01132 01133 { 01134 HWND hWnd; 01135 01136 Console->Flags |= CONSOLE_TERMINATING; 01137 NtSetEvent(Console->TerminationEvent,NULL); 01138 hWnd = Console->hWnd; 01139 01140 // 01141 // Wait 10 seconds or until the input thread replies 01142 // to synchronize the window destruction with 01143 // the termination of the thread 01144 // 01145 01146 if (hWnd != NULL) { 01147 UnlockConsole(Console); 01148 SendMessageTimeout(hWnd, CM_DESTROY_WINDOW, 0, 0, SMTO_BLOCK, 10000, NULL); 01149 } else { 01150 AbortCreateConsole(Console); 01151 } 01152 } 01153 01154 VOID 01155 InsertScreenBuffer( 01156 IN PCONSOLE_INFORMATION Console, 01157 IN PSCREEN_INFORMATION ScreenInfo 01158 ) 01159 01160 /*++ 01161 01162 Routine Description: 01163 01164 This routine inserts the screen buffer pointer into the console's 01165 list of screen buffers. 01166 01167 Arguments: 01168 01169 Console - Pointer to console information structure. 01170 01171 ScreenInfo - Pointer to screen information structure. 01172 01173 Return Value: 01174 01175 Note: 01176 01177 The console lock must be held when calling this routine. 01178 01179 --*/ 01180 01181 { 01182 ScreenInfo->Next = Console->ScreenBuffers; 01183 Console->ScreenBuffers = ScreenInfo; 01184 } 01185 01186 VOID 01187 RemoveScreenBuffer( 01188 IN PCONSOLE_INFORMATION Console, 01189 IN PSCREEN_INFORMATION ScreenInfo 01190 ) 01191 01192 /*++ 01193 01194 Routine Description: 01195 01196 This routine removes the screen buffer pointer from the console's 01197 list of screen buffers. 01198 01199 Arguments: 01200 01201 Console - Pointer to console information structure. 01202 01203 ScreenInfo - Pointer to screen information structure. 01204 01205 Return Value: 01206 01207 Note: 01208 01209 The console lock must be held when calling this routine. 01210 01211 --*/ 01212 01213 { 01214 PSCREEN_INFORMATION Prev,Cur; 01215 01216 if (ScreenInfo == Console->ScreenBuffers) { 01217 Console->ScreenBuffers = ScreenInfo->Next; 01218 return; 01219 } 01220 Prev = Cur = Console->ScreenBuffers; 01221 while (Cur != NULL) { 01222 if (ScreenInfo == Cur) 01223 break; 01224 Prev = Cur; 01225 Cur = Cur->Next; 01226 } 01227 ASSERT (Cur != NULL); 01228 if (Cur != NULL) { 01229 Prev->Next = Cur->Next; 01230 } 01231 } 01232 01233 NTSTATUS 01234 GrowIoHandleTable( 01235 IN PCONSOLE_PER_PROCESS_DATA ProcessData 01236 ) 01237 01238 /*++ 01239 01240 Routine Description: 01241 01242 This routine grows the per-process io handle table. 01243 01244 Arguments: 01245 01246 ProcessData - Pointer to the per-process data structure. 01247 01248 Return Value: 01249 01250 --*/ 01251 01252 { 01253 PHANDLE_DATA NewTable; 01254 ULONG i; 01255 ULONG MaxFileHandles; 01256 01257 ASSERT(ProcessData->Foo == 0xF00); 01258 MaxFileHandles = ProcessData->HandleTableSize + CONSOLE_IO_HANDLE_INCREMENT; 01259 NewTable = (PHANDLE_DATA)ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),MaxFileHandles * sizeof(HANDLE_DATA)); 01260 if (NewTable == NULL) { 01261 return STATUS_NO_MEMORY; 01262 } 01263 RtlCopyMemory(NewTable, ProcessData->HandleTablePtr, 01264 ProcessData->HandleTableSize * sizeof(HANDLE_DATA)); 01265 for (i=ProcessData->HandleTableSize;i<MaxFileHandles;i++) { 01266 NewTable[i].HandleType = CONSOLE_FREE_HANDLE; 01267 } 01268 if (ProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES) { 01269 ConsoleHeapFree(ProcessData->HandleTablePtr); 01270 } 01271 ProcessData->HandleTablePtr = NewTable; 01272 ProcessData->HandleTableSize = MaxFileHandles; 01273 ASSERT(ProcessData->Foo == 0xF00); 01274 ASSERT(ProcessData->HandleTableSize != 0); 01275 ASSERT(ProcessData->HandleTableSize <= 0x0000FFFF); 01276 return STATUS_SUCCESS; 01277 } 01278 01279 VOID 01280 FreeProcessData( 01281 IN PCONSOLE_PER_PROCESS_DATA ProcessData 01282 ) 01283 01284 /*++ 01285 01286 Routine Description: 01287 01288 This routine frees any per-process data allocated by the console. 01289 01290 Arguments: 01291 01292 ProcessData - Pointer to the per-process data structure. 01293 01294 Return Value: 01295 01296 --*/ 01297 01298 { 01299 if (ProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES) { 01300 ConsoleHeapFree(ProcessData->HandleTablePtr); 01301 ProcessData->HandleTablePtr = ProcessData->HandleTable; 01302 ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES; 01303 } 01304 } 01305 01306 VOID 01307 InitializeOutputHandle( 01308 PHANDLE_DATA HandleData, 01309 PSCREEN_INFORMATION ScreenBuffer 01310 ) 01311 01312 /*++ 01313 01314 Routine Description: 01315 01316 This routine initializes the output-specific fields of the handle data 01317 structure. 01318 01319 Arguments: 01320 01321 HandleData - Pointer to handle data structure. 01322 01323 ScreenBuffer - Pointer to screen buffer data structure. 01324 01325 Return Value: 01326 01327 --*/ 01328 01329 { 01330 HandleData->Buffer.ScreenBuffer = ScreenBuffer; 01331 HandleData->Buffer.ScreenBuffer->RefCount++; 01332 } 01333 01334 BOOLEAN 01335 InitializeInputHandle( 01336 PHANDLE_DATA HandleData, 01337 PINPUT_INFORMATION InputBuffer 01338 ) 01339 01340 /*++ 01341 01342 Routine Description: 01343 01344 This routine initializes the input-specific fields of the handle data 01345 structure. 01346 01347 Arguments: 01348 01349 HandleData - Pointer to handle data structure. 01350 01351 InputBuffer - Pointer to input buffer data structure. 01352 01353 Return Value: 01354 01355 --*/ 01356 01357 { 01358 NTSTATUS Status; 01359 01360 HandleData->InputReadData = (PINPUT_READ_HANDLE_DATA)ConsoleHeapAlloc(MAKE_TAG( HANDLE_TAG ),sizeof(INPUT_READ_HANDLE_DATA)); 01361 if (!HandleData->InputReadData) { 01362 return FALSE; 01363 } 01364 Status = RtlInitializeCriticalSection(&HandleData->InputReadData->ReadCountLock); 01365 if (!NT_SUCCESS(Status)) { 01366 ConsoleHeapFree(HandleData->InputReadData); 01367 HandleData->InputReadData = NULL; 01368 return FALSE; 01369 } 01370 HandleData->InputReadData->ReadCount = 0; 01371 HandleData->InputReadData->InputHandleFlags = 0; 01372 HandleData->Buffer.InputBuffer = InputBuffer; 01373 HandleData->Buffer.InputBuffer->RefCount++; 01374 return TRUE; 01375 } 01376 01377 VOID 01378 FreeInputHandle( 01379 IN PHANDLE_DATA HandleData 01380 ) 01381 { 01382 if (HandleData->InputReadData) { 01383 RtlDeleteCriticalSection(&HandleData->InputReadData->ReadCountLock); 01384 ConsoleHeapFree(HandleData->InputReadData); 01385 HandleData->InputReadData = NULL; 01386 } 01387 } 01388 01389 NTSTATUS 01390 AllocateIoHandle( 01391 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 01392 IN ULONG HandleType, 01393 OUT PHANDLE Handle 01394 ) 01395 01396 /*++ 01397 01398 Routine Description: 01399 01400 This routine allocates an input or output handle from the process's 01401 handle table. 01402 01403 This routine initializes all non-type specific fields in the handle 01404 data structure. 01405 01406 Arguments: 01407 01408 ProcessData - Pointer to per process data structure. 01409 01410 HandleType - Flag indicating input or output handle. 01411 01412 Handle - On return, contains allocated handle. Handle is an index 01413 internally. When returned to the API caller, it is translated into 01414 a handle. 01415 01416 Return Value: 01417 01418 Note: 01419 01420 The console lock must be held when calling this routine. The handle 01421 is allocated from the per-process handle table. Holding the console 01422 lock serializes both threads within the calling process and any other 01423 process that shares the console. 01424 01425 --*/ 01426 01427 { 01428 ULONG i; 01429 NTSTATUS Status; 01430 01431 for (i=0;i<ProcessData->HandleTableSize;i++) { 01432 if (ProcessData->HandleTablePtr[i].HandleType == CONSOLE_FREE_HANDLE) { 01433 ProcessData->HandleTablePtr[i].HandleType = HandleType; 01434 *Handle = (HANDLE) i; 01435 01436 return STATUS_SUCCESS; 01437 } 01438 } 01439 Status = GrowIoHandleTable(ProcessData); 01440 if (!NT_SUCCESS(Status)) 01441 return Status; 01442 for ( ;i<ProcessData->HandleTableSize;i++) { 01443 if (ProcessData->HandleTablePtr[i].HandleType == CONSOLE_FREE_HANDLE) { 01444 ProcessData->HandleTablePtr[i].HandleType = HandleType; 01445 *Handle = (HANDLE) i; 01446 return STATUS_SUCCESS; 01447 } 01448 } 01449 ASSERT (FALSE); 01450 return STATUS_UNSUCCESSFUL; 01451 } 01452 01453 01454 NTSTATUS 01455 FreeIoHandle( 01456 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 01457 IN HANDLE Handle 01458 ) 01459 01460 /*++ 01461 01462 Routine Description: 01463 01464 This routine frees an input or output handle from the process's 01465 handle table. 01466 01467 Arguments: 01468 01469 ProcessData - Pointer to per process data structure. 01470 01471 Handle - Handle to free. 01472 01473 Return Value: 01474 01475 Note: 01476 01477 The console lock must be held when calling this routine. The handle 01478 is freed from the per-process handle table. Holding the console 01479 lock serializes both threads within the calling process and any other 01480 process that shares the console. 01481 01482 --*/ 01483 01484 { 01485 NTSTATUS Status; 01486 PHANDLE_DATA HandleData; 01487 01488 Status = DereferenceIoHandleNoCheck(ProcessData, 01489 Handle, 01490 &HandleData 01491 ); 01492 ASSERT (NT_SUCCESS(Status)); 01493 if (HandleData->HandleType & CONSOLE_INPUT_HANDLE) { 01494 FreeInputHandle(HandleData); 01495 } 01496 HandleData->HandleType = CONSOLE_FREE_HANDLE; 01497 return STATUS_SUCCESS; 01498 } 01499 01500 NTSTATUS 01501 DereferenceIoHandleNoCheck( 01502 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 01503 IN HANDLE Handle, 01504 OUT PHANDLE_DATA *HandleData 01505 ) 01506 01507 /*++ 01508 01509 Routine Description: 01510 01511 This routine verifies a handle's validity, then returns a pointer to 01512 the handle data structure. 01513 01514 Arguments: 01515 01516 ProcessData - Pointer to per process data structure. 01517 01518 Handle - Handle to dereference. 01519 01520 HandleData - On return, pointer to handle data structure. 01521 01522 Return Value: 01523 01524 --*/ 01525 01526 { 01527 if (((ULONG_PTR)Handle >= ProcessData->HandleTableSize) || 01528 (ProcessData->HandleTablePtr[(ULONG_PTR)Handle].HandleType == CONSOLE_FREE_HANDLE) ) { 01529 return STATUS_INVALID_HANDLE; 01530 } 01531 *HandleData = &ProcessData->HandleTablePtr[(ULONG_PTR)Handle]; 01532 return STATUS_SUCCESS; 01533 } 01534 01535 NTSTATUS 01536 DereferenceIoHandle( 01537 IN PCONSOLE_PER_PROCESS_DATA ProcessData, 01538 IN HANDLE Handle, 01539 IN ULONG HandleType, 01540 IN ACCESS_MASK Access, 01541 OUT PHANDLE_DATA *HandleData 01542 ) 01543 01544 /*++ 01545 01546 Routine Description: 01547 01548 This routine verifies a handle's validity, then returns a pointer to 01549 the handle data structure. 01550 01551 Arguments: 01552 01553 ProcessData - Pointer to per process data structure. 01554 01555 Handle - Handle to dereference. 01556 01557 HandleData - On return, pointer to handle data structure. 01558 01559 Return Value: 01560 01561 --*/ 01562 01563 { 01564 ULONG_PTR Index; 01565 01566 if (!CONSOLE_HANDLE(Handle)) { 01567 return STATUS_INVALID_HANDLE; 01568 } 01569 Index = (ULONG_PTR)HANDLE_TO_INDEX(Handle); 01570 if ((Index >= ProcessData->HandleTableSize) || 01571 (ProcessData->HandleTablePtr[Index].HandleType == CONSOLE_FREE_HANDLE) || 01572 !(ProcessData->HandleTablePtr[Index].HandleType & HandleType) || 01573 !(ProcessData->HandleTablePtr[Index].Access & Access) ) { 01574 return STATUS_INVALID_HANDLE; 01575 } 01576 *HandleData = &ProcessData->HandleTablePtr[Index]; 01577 return STATUS_SUCCESS; 01578 } 01579 01580 01581 ULONG 01582 SrvVerifyConsoleIoHandle( 01583 IN OUT PCSR_API_MSG m, 01584 IN OUT PCSR_REPLY_STATUS ReplyStatus 01585 ) 01586 01587 /*++ 01588 01589 Routine Description: 01590 01591 This routine verifies that a console io handle is valid. 01592 01593 Arguments: 01594 01595 ApiMessageData - Points to parameter structure. 01596 01597 Return Value: 01598 01599 --*/ 01600 01601 { 01602 PCONSOLE_VERIFYIOHANDLE_MSG a = (PCONSOLE_VERIFYIOHANDLE_MSG)&m->u.ApiMessageData; 01603 PCONSOLE_INFORMATION Console; 01604 NTSTATUS Status; 01605 PHANDLE_DATA HandleData; 01606 PCONSOLE_PER_PROCESS_DATA ProcessData; 01607 01608 UNREFERENCED_PARAMETER(ReplyStatus); 01609 01610 Status = ApiPreamble(a->ConsoleHandle, 01611 &Console 01612 ); 01613 if (NT_SUCCESS(Status)) { 01614 ProcessData = CONSOLE_PERPROCESSDATA(); 01615 Status = DereferenceIoHandleNoCheck(ProcessData, 01616 HANDLE_TO_INDEX(a->Handle), 01617 &HandleData 01618 ); 01619 UnlockConsole(Console); 01620 } 01621 a->Valid = (NT_SUCCESS(Status)); 01622 return STATUS_SUCCESS; 01623 } 01624 01625 01626 NTSTATUS 01627 ApiPreamble( 01628 IN HANDLE ConsoleHandle, 01629 OUT PCONSOLE_INFORMATION *Console 01630 ) 01631 { 01632 NTSTATUS Status; 01633 01634 // 01635 // If this process doesn't have a console handle, bail immediately. 01636 // 01637 01638 if (ConsoleHandle == NULL || ConsoleHandle != CONSOLE_GETCONSOLEHANDLE()) { 01639 return STATUS_INVALID_HANDLE; 01640 } 01641 01642 #ifdef i386 01643 //Do not lock the console if we are in the special case: 01644 //(1). we are in the middle of handshaking with ntvdm doing 01645 // full-screen to windowed mode transition 01646 //(2). the calling process is THE ntvdm process(this implies that the 01647 // the console has vdm registered. 01648 //(3). the console handle is the same one. 01649 // if (1), (2) and (3) are true then the console is already locked 01650 // (locked by the windowproc while processing the WM_FULLSCREEN 01651 // message) 01652 01653 RtlEnterCriticalSection(&ConsoleVDMCriticalSection); 01654 if (ConsoleVDMOnSwitching != NULL && 01655 ConsoleVDMOnSwitching->ConsoleHandle == ConsoleHandle && 01656 ConsoleVDMOnSwitching->VDMProcessId == CONSOLE_CLIENTPROCESSID()) 01657 { 01658 KdPrint((" ApiPreamble - Thread %lx Entered VDM CritSec\n", GetCurrentThreadId())); 01659 *Console = ConsoleVDMOnSwitching; 01660 return STATUS_SUCCESS; 01661 } 01662 RtlLeaveCriticalSection(&ConsoleVDMCriticalSection); 01663 #endif 01664 01665 Status = RevalidateConsole(ConsoleHandle, 01666 Console 01667 ); 01668 if (!NT_SUCCESS(Status)) { 01669 return((ULONG) Status); 01670 } 01671 01672 // 01673 // Make sure the console has been initialized and the window is valid 01674 // 01675 01676 if ((*Console)->hWnd == NULL || ((*Console)->Flags & CONSOLE_TERMINATING)) { 01677 KdPrint(("CONSRV: bogus window for console %lx\n", *Console)); 01678 UnlockConsole(*Console); 01679 return STATUS_INVALID_HANDLE; 01680 } 01681 01682 return Status; 01683 } 01684 01685 NTSTATUS 01686 RevalidateConsole( 01687 IN HANDLE ConsoleHandle, 01688 OUT PCONSOLE_INFORMATION *Console 01689 ) 01690 { 01691 NTSTATUS Status; 01692 01693 LockConsoleHandleTable(); 01694 Status = DereferenceConsoleHandle(ConsoleHandle, 01695 Console 01696 ); 01697 if (!NT_SUCCESS(Status)) { 01698 UnlockConsoleHandleTable(); 01699 return Status; 01700 } 01701 01702 // 01703 // The WaitCount ensures the console won't go away between the time 01704 // we unlock the console handle table and we lock the console. 01705 // 01706 01707 InterlockedIncrement(&(*Console)->WaitCount); 01708 UnlockConsoleHandleTable(); 01709 try { 01710 LockConsole(*Console); 01711 } except (EXCEPTION_EXECUTE_HANDLER) { 01712 InterlockedDecrement(&(*Console)->WaitCount); 01713 return GetExceptionCode(); 01714 } 01715 InterlockedDecrement(&(*Console)->WaitCount); 01716 01717 // 01718 // If the console was marked for destruction while we were waiting to 01719 // lock it, try to destroy it and return. 01720 // 01721 01722 if ((*Console)->Flags & CONSOLE_IN_DESTRUCTION) { 01723 DestroyConsole(*Console); 01724 *Console = NULL; 01725 return STATUS_INVALID_HANDLE; 01726 } 01727 01728 // 01729 // If the console was marked for termination while we were waiting to 01730 // lock it, bail out. 01731 // 01732 01733 if ((*Console)->Flags & CONSOLE_TERMINATING) { 01734 UnlockConsole(*Console); 01735 *Console = NULL; 01736 return STATUS_PROCESS_IS_TERMINATING; 01737 } 01738 01739 return Status; 01740 } 01741 01742 01743 #if DBG 01744 01745 BOOLEAN 01746 UnProtectHandle( 01747 HANDLE hObject 01748 ) 01749 { 01750 NTSTATUS Status; 01751 OBJECT_HANDLE_FLAG_INFORMATION HandleInfo; 01752 01753 Status = NtQueryObject(hObject, 01754 ObjectHandleFlagInformation, 01755 &HandleInfo, 01756 sizeof(HandleInfo), 01757 NULL 01758 ); 01759 if (NT_SUCCESS(Status)) { 01760 HandleInfo.ProtectFromClose = FALSE; 01761 Status = NtSetInformationObject(hObject, 01762 ObjectHandleFlagInformation, 01763 &HandleInfo, 01764 sizeof(HandleInfo) 01765 ); 01766 if (NT_SUCCESS(Status)) { 01767 return TRUE; 01768 } 01769 } 01770 01771 return FALSE; 01772 } 01773 01774 #endif // DBG

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