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

channel.c File Reference

#include "ki.h"

Go to the source code of this file.

Functions

VOID KiAllocateReceiveBufferChannel (VOID)
VOID KiCloseChannel (IN PEPROCESS Process, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
VOID KiDeleteChannel (IN PVOID Object)
NTSTATUS KiListenChannel (IN PRECHANNEL ServerChannel, IN KPROCESSOR_MODE WaitMode, OUT PCHANNEL_MESSAGE *Message)
PKTHREAD KiRendezvousWithThread (IN PRECHANNEL WaitChannel, IN ULONG WaitMode)
NTSTATUS NtCreateChannel (OUT PHANDLE ChannelHandle, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL)
NTSTATUS NtListenChannel (IN HANDLE ChannelHandle, OUT PCHANNEL_MESSAGE *Message)
NTSTATUS NtOpenChannel (OUT PHANDLE ChannelHandle, IN POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS NtReplyWaitSendChannel (IN PVOID Text, IN ULONG Length, OUT PCHANNEL_MESSAGE *Message)
NTSTATUS NtSendWaitReplyChannel (IN HANDLE ChannelHandle, IN PVOID Text, IN ULONG Length, OUT PCHANNEL_MESSAGE *Message)
NTSTATUS NtSetContextChannel (IN PVOID Context)

Variables

POBJECT_TYPE KeChannelType
GENERIC_MAPPING KiChannelMapping


Function Documentation

VOID KiAllocateReceiveBufferChannel VOID   ) 
 

Referenced by NtListenChannel(), NtReplyWaitSendChannel(), and NtSendWaitReplyChannel().

VOID KiCloseChannel IN PEPROCESS  Process,
IN PVOID  Object,
IN ACCESS_MASK  GrantedAccess,
IN ULONG  ProcessHandleCount,
IN ULONG  SystemHandleCount
 

VOID KiDeleteChannel IN PVOID  Object  ) 
 

NTSTATUS KiListenChannel IN PRECHANNEL  ServerChannel,
IN KPROCESSOR_MODE  WaitMode,
OUT PCHANNEL_MESSAGE *  Message
 

Referenced by NtListenChannel(), and NtReplyWaitSendChannel().

PKTHREAD KiRendezvousWithThread IN PRECHANNEL  WaitChannel,
IN ULONG  WaitMode
 

Referenced by NtReplyWaitSendChannel(), and NtSendWaitReplyChannel().

NTSTATUS NtCreateChannel OUT PHANDLE  ChannelHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL
 

Definition at line 101 of file channel.c.

References _ECHANNEL::ClearToSendEvent, _ECHANNEL::ClientThread, ECHANNEL, ExSystemExceptionFilter(), FALSE, KeChannelType, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, LISTEN_CHANNEL, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), ObjectAttributes, _ECHANNEL::OwnerProcess, ProbeAndZeroHandle, PsGetCurrentProcess, _ECHANNEL::ReceiveEvent, _ECHANNEL::ServerChannel, _ECHANNEL::ServerContext, ServerIdle, _ECHANNEL::ServerThread, _ECHANNEL::State, Status, and _ECHANNEL::Type.

00108 : 00109 00110 This function creates a server listen channel object and opens a handle 00111 to the object with the specified desired access. 00112 00113 Arguments: 00114 00115 ChannelHandle - Supplies a pointer to a variable that will receive the 00116 channel object handle. 00117 00118 ObjectAttributes - Supplies a pointer to an object attributes structure. 00119 00120 Return Value: 00121 00122 If the channel object is created, then a success status is returned. 00123 Otherwise, a failure status is returned. 00124 00125 --*/ 00126 00127 { 00128 00129 #if 0 00130 00131 PVOID ChannelObject; 00132 KPROCESSOR_MODE PreviousMode; 00133 PRECHANNEL ServerChannel; 00134 HANDLE ServerHandle; 00135 NTSTATUS Status; 00136 00137 // 00138 // Establish an exception handler, probe and zero the output handle 00139 // address, and attempt to create a channel object. If the probe fails 00140 // or access to the object attributes fails, then return the exception 00141 // code as the service status. 00142 // 00143 00144 PreviousMode = KeGetPreviousMode(); 00145 try { 00146 00147 // 00148 // Get previous processor mode and probe output handle address if 00149 // necessary. 00150 // 00151 00152 if (PreviousMode != KernelMode) { 00153 ProbeAndZeroHandle(ChannelHandle); 00154 } 00155 00156 // 00157 // Allocate channel object. 00158 // 00159 00160 Status = ObCreateObject(PreviousMode, 00161 KeChannelType, 00162 ObjectAttributes, 00163 PreviousMode, 00164 NULL, 00165 sizeof(ECHANNEL), 00166 0, 00167 0, 00168 &ChannelObject); 00169 00170 } except(ExSystemExceptionFilter()) { 00171 return GetExceptionCode(); 00172 } 00173 00174 // 00175 // If the channel object was successfully created, then initialize the 00176 // channel object and insert the channel object in the process handle 00177 // table. 00178 // 00179 00180 if (NT_SUCCESS(Status)) { 00181 ServerChannel = (PRECHANNEL)ChannelObject; 00182 ServerChannel->Type = LISTEN_CHANNEL; 00183 ServerChannel->State = ServerIdle; 00184 ServerChannel->OwnerProcess = &PsGetCurrentProcess()->Pcb; 00185 ServerChannel->ClientThread = NULL; 00186 ServerChannel->ServerThread = NULL; 00187 ServerChannel->ServerContext = NULL; 00188 ServerChannel->ServerChannel = NULL; 00189 KeInitializeEvent(&ServerChannel->ReceiveEvent, 00190 SynchronizationEvent, 00191 FALSE); 00192 00193 KeInitializeEvent(&ServerChannel->ClearToSendEvent, 00194 SynchronizationEvent, 00195 FALSE); 00196 00197 Status = ObInsertObject(ServerChannel, 00198 NULL, 00199 CHANNEL_ALL_ACCESS, 00200 0, 00201 NULL, 00202 &ServerHandle); 00203 00204 // 00205 // If the channel object was successfully inserted in the process 00206 // handle table, then attempt to write the channel object handle 00207 // value. If the write attempt fails, then do not report an error. 00208 // When the caller attempts to access the handle value, an access 00209 // violation will occur. 00210 // 00211 00212 if (NT_SUCCESS(Status)) { 00213 try { 00214 *ChannelHandle = ServerHandle; 00215 00216 } except(ExSystemExceptionFilter()) { 00217 } 00218 } 00219 } 00220 00221 // 00222 // Return service status. 00223 // 00224 00225 return Status; 00226 00227 #else 00228 00229 return STATUS_NOT_IMPLEMENTED; 00230 00231 #endif 00232 00233 }

NTSTATUS NtListenChannel IN HANDLE  ChannelHandle,
OUT PCHANNEL_MESSAGE *  Message
 

Definition at line 236 of file channel.c.

References ExSystemExceptionFilter(), KeChannelType, KeGetCurrentThread, KernelMode, KiAllocateReceiveBufferChannel(), KiListenChannel(), KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), ProbeAndNullPointer, _ECHANNEL::ServerChannel, ServerThread(), and Status.

00243 : 00244 00245 This function listens for a client message. 00246 00247 N.B. This function can only be executed from a server thread. 00248 00249 Arguments: 00250 00251 ChannelHandle - Supplies a handle to a listen channel on which the 00252 server thread listens. 00253 00254 Message - Supplies a pointer to a variable that receives a pointer 00255 to the client message header. 00256 00257 Return Value: 00258 00259 If the function is successfully completed, then a success status is 00260 returned. Otherwise, a failure status is returned. 00261 00262 --*/ 00263 00264 { 00265 00266 #if 0 00267 00268 KPROCESSOR_MODE PreviousMode; 00269 PRECHANNEL ServerChannel; 00270 PRKTHREAD ServerThread; 00271 NTSTATUS Status; 00272 00273 // 00274 // Establish an exception handler, probe the output message address, 00275 // and allocate a receive buffer if necessary. If the probe fails or 00276 // the receive buffer allocation is not successful, then return the 00277 // exception code as the service status. 00278 // 00279 00280 ServerThread = KeGetCurrentThread(); 00281 try { 00282 00283 // 00284 // Get previous processor mode and probe output message address. 00285 // 00286 00287 PreviousMode = KeGetPreviousMode(); 00288 if (PreviousMode != KernelMode) { 00289 ProbeAndNullPointer(Message); 00290 } 00291 00292 // 00293 // If the current thread does not have an associated receive buffer, 00294 // then attempt to allocate one now. If the allocation fails, then 00295 // an exception is raised. 00296 // 00297 00298 if (ServerThread->Section == NULL) { 00299 KiAllocateReceiveBufferChannel(); 00300 } 00301 00302 } except(ExSystemExceptionFilter()) { 00303 return GetExceptionCode(); 00304 } 00305 00306 // 00307 // Reference channel object by handle. 00308 // 00309 00310 Status = ObReferenceObjectByHandle(ChannelHandle, 00311 CHANNEL_ALL_ACCESS, 00312 KeChannelType, 00313 PreviousMode, 00314 &ServerChannel, 00315 NULL); 00316 00317 // 00318 // If the reference was successful and the channel is a listen channel, 00319 // then wait for a client message to arrive. 00320 // 00321 00322 if (NT_SUCCESS(Status)) { 00323 if (ServerChannel->ServerChannel != NULL) { 00324 Status = STATUS_INVALID_PARAMETER; // **** fix **** 00325 00326 } else { 00327 Status = KiListenChannel(ServerChannel, PreviousMode, Message); 00328 } 00329 00330 ObDereferenceObject(ServerChannel); 00331 } 00332 00333 // 00334 // Return service status. 00335 // 00336 00337 return Status; 00338 00339 #else 00340 00341 return STATUS_NOT_IMPLEMENTED; 00342 00343 #endif 00344 00345 }

NTSTATUS NtOpenChannel OUT PHANDLE  ChannelHandle,
IN POBJECT_ATTRIBUTES  ObjectAttributes
 

Definition at line 348 of file channel.c.

References ClientIdle, ClientThread(), ExSystemExceptionFilter(), FALSE, KeChannelType, KeGetCurrentThread, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, MESSAGE_CHANNEL, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), ObjectAttributes, ObReferenceObjectByName(), _ECHANNEL::OwnerProcess, PECHANNEL, ProbeAndZeroHandle, PsGetCurrentProcess, and Status.

00355 : 00356 00357 This function opens a handle to a server channel by creating a message 00358 channel that is connected to the specified server channel. 00359 00360 Arguments: 00361 00362 ChannelHandle - Supplies a pointer to a variable that will receive the 00363 channel object handle. 00364 00365 ObjectAttributes - Supplies a pointer to an object attributes structure. 00366 00367 Return Value: 00368 00369 If the channel object is opened, then a success status is returned. 00370 Otherwise, a failure status is returned. 00371 00372 --*/ 00373 00374 { 00375 00376 #if 0 00377 00378 PRECHANNEL ClientChannel; 00379 HANDLE ClientHandle; 00380 PKTHREAD ClientThread; 00381 KPROCESSOR_MODE PreviousMode; 00382 PRECHANNEL ServerChannel; 00383 PVOID ServerObject; 00384 NTSTATUS Status; 00385 00386 // 00387 // Establish an exception handler, probe and zero the output handle 00388 // address, and attempt to open the server channel object. If the 00389 // probe fails, then return the exception code as the service status. 00390 // 00391 00392 try { 00393 00394 // 00395 // Get previous processor mode and probe output handle address 00396 // if necessary. 00397 // 00398 00399 PreviousMode = KeGetPreviousMode(); 00400 if (PreviousMode != KernelMode) { 00401 ProbeAndZeroHandle(ChannelHandle); 00402 } 00403 00404 // 00405 // Reference the server channel object with the specified desired 00406 // access. 00407 // 00408 00409 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, 00410 ObjectAttributes->Attributes, 00411 NULL, 00412 CHANNEL_ALL_ACCESS, 00413 KeChannelType, 00414 PreviousMode, 00415 NULL, 00416 (PVOID *)&ServerObject); 00417 00418 } except(ExSystemExceptionFilter()) { 00419 return GetExceptionCode(); 00420 } 00421 00422 // 00423 // If the reference was successful, then attempt to create a client 00424 // channel object. 00425 // 00426 00427 if (NT_SUCCESS(Status)) { 00428 00429 // 00430 // If the owner process of the server channel is the same as 00431 // the current process, then a server thread is attempting to 00432 // open a client handle. This is not allowed since it would 00433 // not be possible to distinguish the server from the cient. 00434 // 00435 00436 ClientThread = KeGetCurrentThread(); 00437 ServerChannel = (PECHANNEL)ServerObject; 00438 if (ServerChannel->OwnerProcess == ClientThread->ApcState.Process) { 00439 Status = STATUS_INVALID_PARAMETER; // **** fix *** 00440 00441 } else { 00442 Status = ObCreateObject(PreviousMode, 00443 KeChannelType, 00444 NULL, 00445 PreviousMode, 00446 NULL, 00447 sizeof(ECHANNEL), 00448 0, 00449 0, 00450 (PVOID *)&ClientChannel); 00451 00452 // 00453 // If the channel object was successfully created, then 00454 // initialize the channel object and attempt to insert the 00455 // channel object in the server process channel table. 00456 // 00457 00458 if (NT_SUCCESS(Status)) { 00459 ClientChannel->Type = MESSAGE_CHANNEL; 00460 ClientChannel->State = ClientIdle; 00461 ClientChannel->OwnerProcess = &PsGetCurrentProcess()->Pcb; 00462 ClientChannel->ClientThread = NULL; 00463 ClientChannel->ServerThread = NULL; 00464 ClientChannel->ServerContext = NULL; 00465 ClientChannel->ServerChannel = ServerChannel; 00466 KeInitializeEvent(&ClientChannel->ReceiveEvent, 00467 SynchronizationEvent, 00468 FALSE); 00469 00470 KeInitializeEvent(&ClientChannel->ClearToSendEvent, 00471 SynchronizationEvent, 00472 FALSE); 00473 00474 // 00475 // Create a handle to the message channel object. 00476 // 00477 00478 Status = ObInsertObject(ClientChannel, 00479 NULL, 00480 CHANNEL_ALL_ACCESS, 00481 0, 00482 NULL, 00483 &ClientHandle); 00484 00485 // 00486 // If the channel object was successfully inserted in the 00487 // client process handle table, then attempt to write the 00488 // client channel object handle value. If the write attempt 00489 // fails, then do not report an error. When the caller 00490 // attempts to access the handle value, an access violation 00491 // will occur. 00492 // 00493 00494 if (NT_SUCCESS(Status)) { 00495 try { 00496 *ChannelHandle = ClientHandle; 00497 00498 } except(ExSystemExceptionFilter()) { 00499 } 00500 00501 } 00502 00503 return Status; 00504 } 00505 } 00506 00507 ObDereferenceObject(ServerChannel); 00508 } 00509 00510 // 00511 // Return service status. 00512 // 00513 00514 return Status; 00515 00516 #else 00517 00518 return STATUS_NOT_IMPLEMENTED; 00519 00520 #endif 00521 00522 }

NTSTATUS NtReplyWaitSendChannel IN PVOID  Text,
IN ULONG  Length,
OUT PCHANNEL_MESSAGE *  Message
 

Definition at line 525 of file channel.c.

References CHAR, _ECHANNEL::ClearToSendEvent, ClientIdle, _ECHANNEL::ClientThread, ClientThread(), ExSystemExceptionFilter(), FALSE, _KEVENT::Header, KeGetCurrentThread, KernelMode, KiAllocateReceiveBufferChannel(), KiListenChannel(), KiLockDispatcherDatabase, KiReadyThread(), KiRendezvousWithThread(), KiUnlockDispatcherDatabase(), KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGE_SIZE, ProbeAndNullPointer, ProbeForRead, _ECHANNEL::ReceiveEvent, _ECHANNEL::ServerChannel, ServerReceiveMessage, _ECHANNEL::ServerThread, ServerThread(), _ECHANNEL::State, Status, _DISPATCHER_HEADER::WaitListHead, and WrRendezvous.

00533 : 00534 00535 This function sends a reply message to a client and waits for a send. 00536 00537 N.B. This function can only be executed from a server thread that 00538 has an assoicated message channel. 00539 00540 Arguments: 00541 00542 Text - Supplies a pointer to the message text. 00543 00544 Length - Supplies the length of the message text. 00545 00546 Message - Supplies a pointer to a variable that receives the send 00547 message header. 00548 00549 Return Value: 00550 00551 If the function is successfully completed, then a succes status is 00552 returned. Otherwise, a failure status is returned. 00553 00554 --*/ 00555 00556 { 00557 00558 #if 0 00559 00560 PKTHREAD ClientThread; 00561 PCHANNEL_MESSAGE ClientView; 00562 PRECHANNEL MessageChannel; 00563 KPROCESSOR_MODE PreviousMode; 00564 PECHANNEL ServerChannel; 00565 PKTHREAD ServerThread; 00566 NTSTATUS Status; 00567 00568 // 00569 // Establish an exception handler, probe the output message address, 00570 // probe the message text, and allocate a receive buffer if necessary. 00571 // If either of the probes fail or the receive buffer allocation is 00572 // not successful, then return the exception code as the service 00573 // status. 00574 // 00575 00576 ServerThread = KeGetCurrentThread(); 00577 try { 00578 00579 // 00580 // Get previous processor mode and probe output message address and 00581 // the message text if necessary. 00582 // 00583 00584 PreviousMode = KeGetPreviousMode(); 00585 if (PreviousMode != KernelMode) { 00586 ProbeForRead(Text, Length, sizeof(CHAR)); 00587 ProbeAndNullPointer(Message); 00588 } 00589 00590 // 00591 // If the current thread does not have an associated receive buffer, 00592 // then attempt to allocate one now. If the allocation fails, then 00593 // an exception is raised. 00594 // 00595 00596 if (ServerThread->Section == NULL) { 00597 KiAllocateReceiveBufferChannel(); 00598 } 00599 00600 } except(ExSystemExceptionFilter()) { 00601 return GetExceptionCode(); 00602 } 00603 00604 // 00605 // If the message length is greater than the host page size minus 00606 // the message header length, then return an error. 00607 // 00608 00609 if (Length >= (PAGE_SIZE - sizeof(CHANNEL_MESSAGE))) { 00610 return STATUS_BUFFER_OVERFLOW; 00611 } 00612 00613 // 00614 // If the server thread has an associated message channel, the channel 00615 // is in server receive message state, and the channel server thread 00616 // matches the current thread. 00617 // 00618 // This implies that: 00619 // 00620 // 1. The channel is a message channel. 00621 // 00622 // 2. The channel is being accessed by the server thread. 00623 // 00624 // 3. The channel is associated with a listen channel. 00625 // 00626 // 4. There is currently a server channel owner. 00627 // 00628 // 5. There is currently a client channel owner. 00629 // 00630 00631 KiLockDispatcherDatabase(&ServerThread->WaitIrql); 00632 MessageChannel = ServerThread->Channel; 00633 if ((MessageChannel == NULL) || 00634 (MessageChannel->State != ServerReceiveMessage) || 00635 (MessageChannel->ServerThread != ServerThread)) { 00636 00637 // 00638 // A message is not associated with the current thread, 00639 // the message channel is in the wrong state, or the 00640 // current thread is not the owner of the channel. 00641 // 00642 00643 KiUnlockDispatcherDatabase(ServerThread->WaitIrql); 00644 Status = STATUS_INVALID_PARAMETER; // **** fix **** 00645 00646 } else { 00647 00648 // 00649 // Rendezvous with the client thread so a transfer of the 00650 // reply text to the client thread can occur. 00651 // 00652 00653 ClientThread = KiRendezvousWithThread(MessageChannel, PreviousMode); 00654 00655 // 00656 // Control is returned when: 00657 // 00658 // 1. The server thread is being terminated (USER_APC). 00659 // 00660 // 2. A rendezvous with a client thread has occured. 00661 // 00662 // N.B. If the status value is less than zero, then it 00663 // is the address of the client thread. 00664 // 00665 00666 if ((LONG)ClientThread < 0) { 00667 00668 // 00669 // The client thread is returned as the rendezvous status 00670 // with the thread in the transition state. Get the address 00671 // of the client thread system view, establish an exception 00672 // handler, and transfer the message text from the server's 00673 // buffer to the client's receive buffer. If an exception 00674 // occurs during the copy, then return the exception code 00675 // as the service status. 00676 // 00677 00678 ClientView = ClientThread->SystemView; 00679 Status = STATUS_SUCCESS; 00680 if (Length != 0) { 00681 try { 00682 RtlCopyMemory(ClientView + 1, Text, Length); 00683 00684 } except (ExSystemExceptionFilter()) { 00685 Status = GetExceptionCode(); 00686 } 00687 } 00688 00689 // 00690 // Set the channel message parameters. 00691 // 00692 00693 ClientView->Text = (PVOID)(ClientThread->ThreadView + 1); 00694 ClientView->Length = Length; 00695 ClientView->Context = NULL; 00696 ClientView->Base = Text; 00697 ClientView->Close = FALSE; 00698 00699 // 00700 // Raise IRQL to dispatch level, lock the dispatcher 00701 // database, and check if the message was successfully 00702 // transfered to the client's receive buffer. If the 00703 // message was successfully transfered to the client's 00704 // receive buffer. then reset the channel state, fill 00705 // in the message parameters, ready the client thread, 00706 // and listen for the next message. Otherwise, set the 00707 // client wait status and ready the client thread for 00708 // execution. 00709 // 00710 00711 KiLockDispatcherDatabase(&ServerThread->WaitIrql); 00712 if (NT_SUCCESS(Status)) { 00713 MessageChannel->State = ClientIdle; 00714 MessageChannel->ClientThread = NULL; 00715 MessageChannel->ServerThread = NULL; 00716 ClientThread->WaitStatus = STATUS_SUCCESS; 00717 00718 // 00719 // Reference the server channel and dereference the 00720 // message channel. 00721 // 00722 00723 ServerChannel = MessageChannel->ServerChannel; 00724 ObReferenceObject(ServerChannel); 00725 ObDereferenceObject(MessageChannel); 00726 00727 // 00728 // If there are no clients waiting to send to the server, 00729 // then switch directly to the client thread. Otherwise, 00730 // ready the client thread, then listen for the next 00731 // message. 00732 // 00733 00734 if (IsListEmpty(&ServerChannel->ClearToSendEvent.Header.WaitListHead) == FALSE) { 00735 KiReadyThread(ClientThread); 00736 KiUnlockDispatcherDatabase(ServerThread->WaitIrql); 00737 Status = KiListenChannel(ServerChannel, 00738 PreviousMode, 00739 Message); 00740 00741 } else { 00742 Status = KiSwitchToThread(ClientThread, 00743 WrRendezvous, 00744 PreviousMode, 00745 &ServerChannel->ReceiveEvent); 00746 00747 // 00748 // If a client message was successfully received, then 00749 // attempt to write the address of the send message 00750 // address. If the write attempt fails, then do not 00751 // report an error. When the caller attempts to access 00752 // the message address, an access violation will occur. 00753 // 00754 00755 if (NT_SUCCESS(Status)) { 00756 try { 00757 *Message = ServerThread->ThreadView; 00758 00759 } except(ExSystemExceptionFilter()) { 00760 } 00761 } 00762 } 00763 00764 ObDereferenceObject(ServerChannel); 00765 00766 } else { 00767 00768 // 00769 // The reply message was not successfully transfered 00770 // to the client receive buffer because of an access 00771 // violation encountered durring the access to the 00772 // server buffer. 00773 // 00774 00775 ClientThread->WaitStatus = STATUS_KERNEL_APC; 00776 KiReadyThread(ClientThread); 00777 KiUnlockDispatcherDatabase(ServerThread->WaitIrql); 00778 } 00779 00780 } else { 00781 00782 // 00783 // The server thread is terminating and the channel 00784 // structures will be cleaned up by the termiantion 00785 // code. 00786 // 00787 00788 Status = (NTSTATUS)ClientThread; 00789 } 00790 } 00791 00792 // 00793 // Return service status. 00794 // 00795 00796 return Status; 00797 00798 #else 00799 00800 return STATUS_NOT_IMPLEMENTED; 00801 00802 #endif 00803 00804 }

NTSTATUS NtSendWaitReplyChannel IN HANDLE  ChannelHandle,
IN PVOID  Text,
IN ULONG  Length,
OUT PCHANNEL_MESSAGE *  Message
 

Definition at line 807 of file channel.c.

References ClientIdle, ClientSendWaitReply, ClientThread(), ExSystemExceptionFilter(), FALSE, KeChannelType, KeGetCurrentThread, KernelMode, KiAllocateReceiveBufferChannel(), KiLockDispatcherDatabase, KiReadyThread(), KiRendezvousWithThread(), KiUnlockDispatcherDatabase(), KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, ObReferenceObjectByHandle(), PAGE_SIZE, ProbeAndNullPointer, ProbeForRead, _ECHANNEL::ServerChannel, ServerReceiveMessage, ServerThread(), Status, and WrRendezvous.

00816 : 00817 00818 This function sends a message to a server and waits for a reply. 00819 00820 N.B. This function can only be executed from a client thread. 00821 00822 Arguments: 00823 00824 ChannelHandle - Supplies a handle to a message channel over which the 00825 specified message text is sent. 00826 00827 Text - Supplies a pointer to the message text. 00828 00829 Length - Supplies the length of the message text. 00830 00831 Message - Supplies a pointer to a variable that receives a pointer 00832 to the reply message header. 00833 00834 Return Value: 00835 00836 If the function is successfully completed, then a success status is 00837 returned. Otherwise, a failure status is returned. 00838 00839 --*/ 00840 00841 { 00842 00843 #if 0 00844 00845 PKTHREAD ClientThread; 00846 PRECHANNEL MessageChannel; 00847 KPROCESSOR_MODE PreviousMode; 00848 PRECHANNEL ServerChannel; 00849 PKTHREAD ServerThread; 00850 PCHANNEL_MESSAGE ServerView; 00851 NTSTATUS Status; 00852 00853 // 00854 // Establish an exception handler, probe the output message address, 00855 // probe the message text, and allocate a receive buffer if necessary. 00856 // If either of the probes fail or the receive buffer allocation is 00857 // not successful, then return the exception code as the service 00858 // status. 00859 // 00860 00861 ClientThread = KeGetCurrentThread(); 00862 try { 00863 00864 // 00865 // Get previous processor mode and probe output message address 00866 // and the message text. 00867 // 00868 00869 PreviousMode = KeGetPreviousMode(); 00870 if (PreviousMode != KernelMode) { 00871 ProbeForRead(Text, Length, sizeof(UCHAR)); 00872 ProbeAndNullPointer(Message); 00873 } 00874 00875 // 00876 // If the current thread does not have an associated receive buffer, 00877 // then attempt to allocate one now. If the allocation fails, then 00878 // an exception is raised. 00879 // 00880 00881 if (ClientThread->Section == NULL) { 00882 KiAllocateReceiveBufferChannel(); 00883 } 00884 00885 } except(ExSystemExceptionFilter()) { 00886 return GetExceptionCode(); 00887 } 00888 00889 // 00890 // If the message length is greater than the host page size minus 00891 // the message header length, then return an error. 00892 // 00893 00894 if (Length >= (PAGE_SIZE - sizeof(CHANNEL_MESSAGE))) { 00895 return STATUS_BUFFER_OVERFLOW; 00896 } 00897 00898 // 00899 // Reference channel object by handle. 00900 // 00901 00902 Status = ObReferenceObjectByHandle(ChannelHandle, 00903 CHANNEL_ALL_ACCESS, 00904 KeChannelType, 00905 PreviousMode, 00906 (PVOID *)&MessageChannel, 00907 NULL); 00908 00909 // 00910 // If the reference was successful, then check if the channel is in 00911 // the client idle state. 00912 // 00913 // This implies that: 00914 // 00915 // 1. The channel is a message channel. 00916 // 00917 // 2. The channel is being accessed by a client thread. 00918 // 00919 // 3. The channel is connected to a listen channel. 00920 // 00921 // 4. There is currently no client thread channel owner. 00922 // 00923 // 5. There is currently no server thread channel owner. 00924 // 00925 00926 if (NT_SUCCESS(Status)) { 00927 KiLockDispatcherDatabase(&ClientThread->WaitIrql); 00928 if (MessageChannel->State != ClientIdle) { 00929 00930 // 00931 // The message channel is in the wrong state. 00932 // 00933 00934 KiUnlockDispatcherDatabase(ClientThread->WaitIrql); 00935 Status = STATUS_INVALID_PARAMETER; // **** fix **** 00936 00937 } else { 00938 00939 // 00940 // Set the channel state, set the client owner thread, and 00941 // rendezvous with a server thread. 00942 // 00943 00944 MessageChannel->State = ClientSendWaitReply; 00945 MessageChannel->ClientThread = ClientThread; 00946 ClientThread->Channel = MessageChannel; 00947 ServerChannel = MessageChannel->ServerChannel; 00948 ServerThread = KiRendezvousWithThread(ServerChannel, PreviousMode); 00949 00950 // 00951 // Control is returned when: 00952 // 00953 // 1. The client thread is being terminated (USER_APC). 00954 // 00955 // 2. A rendezvous with a server thread has occured. 00956 // 00957 // N.B. If the status value is less than zero, then it 00958 // is the address of the server thread. 00959 // 00960 00961 if ((LONG)ServerThread < 0) { 00962 00963 // 00964 // The server thread is returned as the rendezvous status 00965 // with the thread in the transition state. Get the address 00966 // of the server thread system view, establish an exception 00967 // handler, and transfer the message text from the client's 00968 // buffer to the server's receive buffer. If an exception 00969 // occurs during the copy, then return the exception code 00970 // as the service status. 00971 // 00972 00973 ServerView = ServerThread->SystemView; 00974 if (Length != 0) { 00975 try { 00976 RtlCopyMemory(ServerView + 1, Text, Length); 00977 00978 } except (ExSystemExceptionFilter()) { 00979 Status = GetExceptionCode(); 00980 } 00981 } 00982 00983 // 00984 // Set the channel message parameters. 00985 // 00986 00987 ServerView->Text = (PVOID)(ServerThread->ThreadView + 1); 00988 ServerView->Length = Length; 00989 ServerView->Context = MessageChannel->ServerContext; 00990 ServerView->Base = Text; 00991 ServerView->Close = FALSE; 00992 00993 // 00994 // Raise IRQL to dispatch level, lock the dispatcher 00995 // database and check if the message was successfully 00996 // transfered to the server's receive buffer. If the 00997 // message was successfully transfered, then set the 00998 // channel state, set the server thread address, set 00999 // the address of the message channel in the server 01000 // thread, increment the message channel reference 01001 // count, fill in the message parameters, and switch 01002 // directly to the server thread. Otherwise, set the 01003 // channel state, and reready the server thread for 01004 // execution. 01005 // 01006 01007 KiLockDispatcherDatabase(&ClientThread->WaitIrql); 01008 if (NT_SUCCESS(Status)) { 01009 MessageChannel->State = ServerReceiveMessage; 01010 MessageChannel->ServerThread = ServerThread; 01011 ObReferenceObject(MessageChannel); 01012 ServerThread->Channel = MessageChannel; 01013 Status = KiSwitchToThread(ServerThread, 01014 WrRendezvous, 01015 PreviousMode, 01016 &MessageChannel->ReceiveEvent); 01017 01018 // 01019 // If the send and subsequent reply from the server 01020 // thread is successful, then attempt to write the 01021 // address of the reply message address. If the write 01022 // attempt fails, then do not report an error. When 01023 // the caller attempts to access the message address, 01024 // an access violation will occur. 01025 // 01026 01027 if (NT_SUCCESS(Status)) { 01028 try { 01029 *Message = ClientThread->ThreadView; 01030 01031 } except(ExSystemExceptionFilter()) { 01032 } 01033 } 01034 01035 } else { 01036 01037 // 01038 // The send message was not successfully transfered 01039 // to the server receive buffer because of an access 01040 // violation encountered durring the access to the 01041 // client buffer. 01042 // 01043 01044 MessageChannel->State = ClientIdle; 01045 MessageChannel->ClientThread = NULL; 01046 ClientThread->Channel = NULL; 01047 ServerThread->WaitStatus = STATUS_KERNEL_APC; 01048 KiReadyThread(ServerThread); 01049 KiUnlockDispatcherDatabase(ClientThread->WaitIrql); 01050 } 01051 01052 } else { 01053 01054 // 01055 // The client thread is terminating and the channel 01056 // structures will be cleaned up by the termination 01057 // code. 01058 // 01059 01060 Status = (NTSTATUS)ServerThread; 01061 } 01062 } 01063 01064 ObDereferenceObject(MessageChannel); 01065 } 01066 01067 // 01068 // Return service status. 01069 // 01070 01071 return Status; 01072 01073 #else 01074 01075 return STATUS_NOT_IMPLEMENTED; 01076 01077 #endif 01078 01079 }

NTSTATUS NtSetContextChannel IN PVOID  Context  ) 
 

Definition at line 1082 of file channel.c.

References KeGetCurrentThread, NTSTATUS(), NULL, _ECHANNEL::ServerContext, _ECHANNEL::ServerThread, and Status.

01088 : 01089 01090 This function stores a context value for the current associated 01091 message channel. 01092 01093 N.B. This function can only be executed from a server thread that 01094 has an associated message channel. 01095 01096 Arguments: 01097 01098 Context - Supplies a context value that is to be stored in the 01099 associated message channel. 01100 01101 Return Value: 01102 01103 If the channel information is set, then a success status is returned. 01104 Otherwise, a failure status is returned. 01105 01106 --*/ 01107 01108 { 01109 01110 #if 0 01111 01112 PRECHANNEL MessageChannel; 01113 PKTHREAD CurrentThread; 01114 NTSTATUS Status; 01115 01116 // 01117 // If the thread has an assoicated channel and the server thread for 01118 // the channel is the current thread, then store the channel context. 01119 // 01120 01121 CurrentThread = KeGetCurrentThread(); 01122 MessageChannel = CurrentThread->Channel; 01123 if ((MessageChannel == NULL) || 01124 (CurrentThread != MessageChannel->ServerThread)) { 01125 Status = STATUS_INVALID_PARAMETER; // ****** FIX ***** 01126 01127 } else { 01128 MessageChannel->ServerContext = Context; 01129 Status = STATUS_SUCCESS; 01130 } 01131 01132 // 01133 // Return service status. 01134 // 01135 01136 return Status; 01137 01138 #else 01139 01140 return STATUS_NOT_IMPLEMENTED; 01141 01142 #endif 01143 01144 }


Variable Documentation

POBJECT_TYPE KeChannelType
 

Definition at line 68 of file channel.c.

Referenced by NtCreateChannel(), NtListenChannel(), NtOpenChannel(), and NtSendWaitReplyChannel().

GENERIC_MAPPING KiChannelMapping
 

Initial value:

{ STANDARD_RIGHTS_READ | CHANNEL_READ_MESSAGE, STANDARD_RIGHTS_WRITE | CHANNEL_WRITE_MESSAGE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, CHANNEL_ALL_ACCESS }

Definition at line 75 of file channel.c.


Generated on Sat May 15 19:43:03 2004 for test by doxygen 1.3.7