📄 btsdpcon.cpp
字号:
PUCHAR pStream = pdu.Write((PUCHAR) u.Client.pRequest);
pStream += u.Client.rawParametersLength;
pContState->Write(pStream);
#if DBG
pStream += pContState->GetTotalSize();
DbgPrint("%d = %d\n", ((PUCHAR) u.Client.pRequest) - pStream,
sizeof(SdpPDU) + pdu.parameterLength);
ASSERT(((ULONG_PTR) (pStream - ((PUCHAR) u.Client.pRequest))) ==
sizeof(SdpPDU) + pdu.parameterLength);
#endif
#if ! ((defined (UNDER_CE) || defined (WINCE_EMULATION)))
ReadAsync();
_RegisterConnectionOnTimer(this, SDP_DEFAULT_TIMEOUT);
Write(u.Client.pRequest, sizeof(SdpPDU) + pdu.parameterLength);
return STATUS_PENDING;
#else
int iRet = Write(u.Client.pRequest, sizeof(SdpPDU) + pdu.parameterLength);
return (iRet==ERROR_SUCCESS) ? STATUS_PENDING : iRet;
#endif
}
NTSTATUS
SdpConnection::OnServiceSearchResponse(
SdpPDU *pPdu,
PUCHAR pBuffer,
ULONG_PTR* pInfo
)
{
SDP_ERROR sdpError;
if (pPdu->transactionId != transactionId-1) {
//
// Server error, ergh
//
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
*pInfo = pRequestorIrp->IoStatus.Information * sizeof(ULONG);
#endif
return STATUS_INVALID_NETWORK_RESPONSE;
}
ContinuationState cs;
USHORT totalCount, currentCount;
ULONG *pHandleList;
USHORT handlesSoFar;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
handlesSoFar = (USHORT) pRequestorIrp->IoStatus.Information;
#else
handlesSoFar = (USHORT) ConnInformation;
#endif
NTSTATUS status = SdpInterface::CrackServerServiceSearchResponse(
pBuffer,
pPdu->parameterLength,
&totalCount,
¤tCount,
&pHandleList,
&cs,
&sdpError
);
if (!NT_SUCCESS(status)) {
//
// Server is giving back garbage
//
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
*pInfo = pRequestorIrp->IoStatus.Information * sizeof(ULONG);
#endif
return STATUS_INVALID_NETWORK_RESPONSE;
}
if (u.Client.ServiceSearch.totalRecordCount == 0) {
//
// First response
//
u.Client.ServiceSearch.totalRecordCount = totalCount;
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
cClientBuf = totalCount*sizeof(unsigned long);
if (cClientBuf) {
pClientBuf = (unsigned char*) ExAllocatePoolWithTag(0,cClientBuf,0);
if (!pClientBuf) {
return ERROR_OUTOFMEMORY;
}
}
#endif // UNDER_CE
}
else if (u.Client.ServiceSearch.totalRecordCount != totalCount) {
//
// Server is giving back inconsistent results, stop sending requests
//
*pInfo = handlesSoFar * sizeof(ULONG);
return STATUS_INVALID_NETWORK_RESPONSE;
}
if (handlesSoFar + currentCount > totalCount) {
//
// Well, the server gave us too many handles.
//
// TBD: do we notify the user of this? if so, how?
//
// just copy over what we can for right now
//
currentCount = totalCount - handlesSoFar;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
PULONG pResult = (PULONG) pRequestorIrp->AssociatedIrp.SystemBuffer;
#else
PULONG pResult = (PULONG) pClientBuf;
#endif
for (ULONG i = 0; i < currentCount; i++) {
ULONG handle;
//
// pHandleList may not be correctly aligned
//
RtlRetrieveUlong(&handle, (pHandleList+i));
pResult[handlesSoFar + i] = RtlUlongByteSwap(handle);
}
handlesSoFar += currentCount;
if (handlesSoFar == totalCount) {
//
// All done
//
*pInfo = handlesSoFar * sizeof(ULONG);
return STATUS_SUCCESS;
}
else {
//
// Not all done, must ask for more
//
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
pRequestorIrp->IoStatus.Information = handlesSoFar;
#else
ConnInformation = handlesSoFar;
#endif
return SendContinuationRequestToServer(&cs);
}
}
NTSTATUS
SdpConnection::OnServiceAttributeResponse(
SdpPDU *pPdu,
PUCHAR pBuffer,
ULONG_PTR* pInfo
)
{
SDP_ERROR sdpError;
if (pPdu->transactionId != transactionId-1) {
//
// Server erorr, ergh
//
SdpPrint(SDP_DBG_CLIENT_WARNING, ("invalid transaction id!"));
return STATUS_INVALID_NETWORK_RESPONSE;
}
ContinuationState cs;
UCHAR *pAttribList;
USHORT listByteCount;
NTSTATUS status = SdpInterface::CrackServerServiceAttributeResponse(
pBuffer,
pPdu->parameterLength,
&listByteCount,
&pAttribList,
&cs,
&sdpError);
if (!NT_SUCCESS(status)) {
return STATUS_INVALID_NETWORK_RESPONSE;
}
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
ULONG bytesSoFar;
ULONG storageSize;
UCHAR type, sizeIndex;
bytesSoFar = ConnInformation;
if (bytesSoFar == 0) {
SdpRetrieveHeader(pAttribList, type, sizeIndex);
if (type != (UCHAR) SDP_TYPE_SEQUENCE) {
return STATUS_INVALID_PARAMETER;
}
if (sizeIndex < 5 || sizeIndex > 7) {
return STATUS_INVALID_PARAMETER;
}
SdpRetrieveVariableSize(pAttribList+1,
sizeIndex,
&u.Client.AttributeSearch.responseLength,
&storageSize);
u.Client.AttributeSearch.responseLength += (storageSize + sizeof(UCHAR));
pClientBuf = (unsigned char*) ExAllocatePoolWithTag(0,u.Client.AttributeSearch.responseLength,0);
cClientBuf = u.Client.AttributeSearch.responseLength;
if (!pClientBuf) {
return ERROR_OUTOFMEMORY;
}
}
if (bytesSoFar + listByteCount > u.Client.AttributeSearch.responseLength) {
// server sent us too much data
return STATUS_INVALID_NETWORK_RESPONSE;
}
memcpy(pClientBuf+bytesSoFar,pAttribList,listByteCount);
ConnInformation += listByteCount;
if (cs.size == 0) {
return ERROR_SUCCESS;
}
else {
return SendContinuationRequestToServer(&cs);
}
#else // UNDER_CE
BthSdpStreamResponse *pResponse;
PIO_STACK_LOCATION stack;
ULONG outLen, responseSize;
ULONG_PTR bytesSoFar;
stack = IoGetCurrentIrpStackLocation(pRequestorIrp);
pResponse = (BthSdpStreamResponse *) pRequestorIrp->AssociatedIrp.SystemBuffer;
outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
responseSize = outLen - (sizeof(*pResponse) - sizeof(pResponse->response));
bytesSoFar = pRequestorIrp->IoStatus.Information;
if (bytesSoFar == 0) {
//
// Retrieve the size from first part of the response
//
ULONG respTotalSize;
ULONG storageSize;
UCHAR type, sizeIndex;
SdpRetrieveHeader(pAttribList, type, sizeIndex);
if (type != (UCHAR) SDP_TYPE_SEQUENCE) {
return STATUS_INVALID_PARAMETER;
}
if (sizeIndex < 5 || sizeIndex > 7) {
return STATUS_INVALID_PARAMETER;
}
SdpRetrieveVariableSize(pAttribList+1,
sizeIndex,
&u.Client.AttributeSearch.responseLength,
&storageSize);
//
// Take header and the storage space needed for the size into account
//
u.Client.AttributeSearch.responseLength += (storageSize + sizeof(UCHAR));
DbgPrint("----: total response length is %d\n", u.Client.AttributeSearch.responseLength);
if (u.Client.AttributeSearch.responseLength > responseSize) {
//
// We must cache off the request before we start copying the response
// because they share the same buffer
//
SdpAttributeRange *pRange;
ULONG numRange;
if (stack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_BTH_SDP_ATTRIBUTE_SEARCH) {
BthSdpAttributeSearchRequest *pSearch =
(BthSdpAttributeSearchRequest *)
pRequestorIrp->AssociatedIrp.SystemBuffer;
numRange = (stack->Parameters.DeviceIoControl.InputBufferLength -
(sizeof(*pSearch) - sizeof(pSearch->range))) /
sizeof(SdpAttributeRange);
pRange = pSearch->range;
u.Client.lastPduRequest = SdpPDU_ServiceAttributeRequest;
}
else {
//
// ServiceSearchAttributeRequest
//
BthSdpServiceAttributeSearchRequest *pSearch =
(BthSdpServiceAttributeSearchRequest *)
pRequestorIrp->AssociatedIrp.SystemBuffer;
numRange = (stack->Parameters.DeviceIoControl.InputBufferLength -
(sizeof(*pSearch) - sizeof(pSearch->range))) /
sizeof(SdpAttributeRange);
pRange = pSearch->range;
// Save off the uuids as well
RtlCopyMemory(u.Client.lastUuid,
pSearch->uuids,
sizeof(u.Client.lastUuid));
u.Client.lastPduRequest = SdpPDU_ServiceSearchAttributeRequest;
}
u.Client.pLastRange = new(PagedPool, SDPC_TAG) SdpAttributeRange[numRange];
if (u.Client.pLastRange) {
u.Client.AttributeSearch.pResponse =
new(PagedPool, SDPC_TAG) UCHAR[u.Client.AttributeSearch.responseLength];
if (u.Client.AttributeSearch.pResponse) {
RtlCopyMemory(u.Client.pLastRange,
pRange,
numRange * sizeof(SdpAttributeRange));
u.Client.numRange = numRange;
}
else {
return STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
return STATUS_INSUFFICIENT_RESOURCES;
}
}
}
DbgPrint("----: bytes so far (%d), current PDU (%d)\n", bytesSoFar, listByteCount);
if (bytesSoFar + listByteCount > u.Client.AttributeSearch.responseLength) {
//
// server sent us too much data
//
return STATUS_INVALID_NETWORK_RESPONSE;
}
if (u.Client.AttributeSearch.pResponse) {
// copy to cache
RtlCopyMemory(u.Client.AttributeSearch.pResponse + bytesSoFar,
pAttribList,
listByteCount);
}
else {
// copy to requestor buffer
RtlCopyMemory(pResponse->response + bytesSoFar,
pAttribList,
listByteCount);
}
pRequestorIrp->IoStatus.Information = bytesSoFar + listByteCount;
if (cs.size == 0) {
DbgPrint("----: we are done!\n");
//
// We are done, give the user his response back
//
ASSERT(pRequestorIrp->IoStatus.Information ==
u.Client.AttributeSearch.responseLength);
//
// Everything but the response buffer for now
//
*pInfo = sizeof(*pResponse) - sizeof(pResponse->response);
if (u.Client.AttributeSearch.pResponse) {
DbgPrint("----: not enough client space to fill in, caching\n");
//
// Not enough room in the user buffer to give the entire response
// back, so copy as much as possible
//
RtlCopyMemory(pResponse->response,
u.Client.AttributeSearch.pResponse,
responseSize);
pResponse->responseSize = responseSize;
pResponse->requiredSize = u.Client.AttributeSearch.responseLength;
status = STATUS_BUFFER_TOO_SMALL;
}
else {
DbgPrint("----: enough room!!!\n");
//
// There is enough room for all
//
pResponse->requiredSize = (ULONG) pRequestorIrp->IoStatus.Information;
pResponse->responseSize = pResponse->requiredSize;
status = STATUS_SUCCESS;
}
*pInfo += pResponse->responseSize;
return status;
}
else {
DbgPrint("----: get more from the server!\n");
//
// get more info from the server
//
return SendContinuationRequestToServer(&cs);
}
#endif // UNDER_CE
}
NTSTATUS
SdpConnection::OnServiceSearchAttributeResponse(
SdpPDU *pPdu,
PUCHAR pBuffer,
ULONG_PTR* pInfo
)
{
return OnServiceAttributeResponse(pPdu, pBuffer, pInfo);
}
BOOLEAN
SdpConnection::IsRequestContinuation(
SdpPDU *pPdu,
PUCHAR pRequest,
ContinuationState *pConStateReq,
BOOLEAN &cleanUpRequired,
BOOLEAN &contError
)
{
contError = FALSE;
if (u.Server.pClientRequest == NULL) {
cleanUpRequired = FALSE;
if (pConStateReq->size != 0) {
contError = TRUE;
}
return FALSE;
}
cleanUpRequired = TRUE;
if (pPdu->pduId != u.Server.lastPduRequest) {
return FALSE;
}
ContinuationState cs(this);
ULONG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -