Functional Description

The SMB_COM_TRANSACTION command's scope includes named pipes and mailslots. Where the resource is unidirectional (such as class 2 writes to mailslots), bit1 of Flags in the request can be set indicating that no response is needed. The other transactions accommodate IOCTL requests and file system requests which require the transfer of an extended attribute list.

The transaction Setup information and/or Parameters define functions specific to a particular resource on a particular server. Therefore the functions supported are not defined by the protocol, but by client and server implementations. The transaction protocol simply provides a means of delivering them and retrieving the results.

The number of bytes needed in order to perform the transaction request may be more than will fit in a single buffer.

At the time of the request, the client knows the number of parameter and data bytes expected to be sent and passes this information to the server via the primary request (TotalParameterCount and TotalDataCount). This may be reduced by lowering the total number of bytes expected (TotalParameterCount and TotalDataCount) in each (if any) secondary request.

When the amount of parameter bytes received (total of each ParameterCount) equals the total amount of parameter bytes expected (smallest TotalParameterCount) received, then the server has received all the parameter bytes.

Likewise, when the amount of data bytes received (total of each datacount) equals the total amount of data bytes expected (smallest totaldatacount) received, then the server has received all the data bytes.

The parameter bytes should normally be sent first followed by the data bytes. However, the server knows where each begins and ends in each buffer by the offset fields (parameteroffset and dataoffset) and the length fields (parametercount and datacount). The displacement of the bytes (relative to start of each) is also known (parameterdisplacement and datadisplacement). Thus the server is able to reassemble the parameter and data bytes should the individual requests be received out of sequence.

If all parameter bytes and data bytes fit into a single buffer, then no interim response is expected and no secondary request is sent.

The client knows the maximum amount of data bytes and parameter bytes which the server may return (from maxparametercount and maxdatacount of the request). Thus the client initializes its bytes expected variables to these values. The server then informs the client of the actual amounts being returned via each message of the server response (totalparametercount and totaldatacount). The server may reduce the expected bytes by lowering the total number of bytes expected (totalparametercount and/or totaldatacount) in each (any) response.

When the amount of parameter bytes received (total of each parametercount) equals the total amount of parameter bytes expected (smallest totalparametercount) received, then the client has received all the parameter bytes.

Likewise, when the amount of data bytes received (total of each datacount) equals the total amount of data bytes expected (smallest totaldatacount) received, then the client has received all the data bytes.

The parameter bytes should normally be returned first followed by the data bytes. However, the client knows where each begins and ends in each buffer by the offset fields (parameteroffset and dataoffset) and the length fields (parametercount and datacount). The displacement of the bytes (relative to start of each) is also known (parameterdisplacement and datadisplacement). The client is able to reassemble the parameter and data bytes should the server responses be received out of sequence.

If a connectionless transport is being used, the transaction requests must be properly sequenced in the connectionless.sequencenumber SMB header field. The mid of any secondary client requests must match the mid of the primary client request. The server responds to each request piece except the last one with a response indicating that the server is ready for the next piece. The last piece is responded to with the first piece of the result data. The client then sends an SMB_COM_TRANSACTION_SECONDARY SMB with parameterdisplacement set to the number of parameter bytes received so far and datadisplacement set to the number of data bytes received so far and parametercount, parameteroffset, datacount, and dataoffset set to zero (0). The server responds with the next piece of the transaction result. The process is repeated until all of the response information has been received. When the transaction has been completed, the client must send another sequenced command (such as an SMB_COM_ECHO) to the server to allow the server to know that the final piece was received and that resources allocated to the transaction command may be released.

The flow for these transactions over a connection oriented transport is:

  1. The client sends the primary client request identifying the total bytes (both parameters and data) which are expected to be sent and contains the set up words and as many of the parameter and data bytes as will fit in a negotiated size buffer. This request also identifies the maximum number of bytes (setup, parameters and data) the server is to return on the transaction completion. If all the bytes fit in the single buffer, skip to step 4.
  2. The server responds with a single interim response meaning "OK, send the remainder of the bytes" or (if error response) terminate the transaction.
  3. The client then sends another buffer full of bytes to the server. This step is repeated until all of the bytes are sent and received.
  4. The Server sets up and performs the transaction with the information provided.
  5. Upon completion of the transaction, the server sends back (up to) the number of parameter and data bytes requested (or as many as will fit in the negotiated buffer size). This step is repeated until all result bytes have been returned.

The flow for the transaction protocol when the request parameters and data do not all fit in a single buffer is:

Client
===============================
<->
====
Server
==============================
Primary TRANSACTION request ->
<- Interim Server Response
Secondary TRANSACTION request 1 ->
Secondary TRANSACTION request 2 ->
Secondary TRANSACTION request N ->
<- TRANSACTION response 1
<- TRANSACTION response 2
<- TRANSACTION response m

The flow for the transaction protocol when the request parameters and data does all fit in a single buffer is:

Client
===============================
<->
====
Server
==============================
Primary TRANSACTION request ->
<- TRANSACTION response 1
<- TRANSACTION response 2
<- TRANSACTION response m

The flow for the transaction protocol over a connectionless transport is:

  1. The client sends the primary client request identifying the total bytes (both parameters and data) which are expected to be sent and contains the set up words and as many of the parameter and data bytes as will fit in a negotiated size buffer. This request also identifies the maximum number of bytes (setup, parameters and data) the server is to return on completion. If all the bytes fit in the single buffer, skip to step 4.
  2. The server responds with a single interim response meaning "OK, send the remainder of the bytes" or (if error response) terminate the transaction.
  3. The client then sends another buffer full of bytes to the server. The server responds with an interim server response. This step is repeated until all of the bytes are sent and received.
  4. The Server sets up and performs the transaction with the information provided.
  5. Upon completion of the transaction, the server sends back (up to) the number of parameter and data bytes requested (or as many as will fit in the negotiated buffer size).
  6. The client responds with a transaction secondary request. The server sends back more response data. This step is repeated until all result bytes have been returned.
    1. The client sends a sequenced request to the server such as SMB_COM_ECHO

The primary transaction request through the final response make up the complete transaction exchange, thus the tid, pid, uid and mid must remain constant and can be used as appropriate by both the server and the client. Of course, other SMB requests may intervene as well.

There are (at least) three ways that actual server responses have been observed to differ from what might be expected. First, some servers will send Pad bytes to move the DataOffset to a 2- or 4-byte boundary even if there are no data bytes; the point here is that the ByteCount must be used instead of ParameterOffset plus ParameterCount to infer the actual message length. Second, some servers always return MaxParameterCount bytes even if the particular Transact2 has no parameter response. Finally, in case of an error, some servers send the "traditional WordCount==0/ByteCount==0" response while others generate a Transact response format.