test: channel.c File Reference

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.