Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrpc_message.c
Go to the documentation of this file.
00001 /* 00002 * RPC messages 00003 * 00004 * Copyright 2001-2002 Ove Kåven, TransGaming Technologies 00005 * Copyright 2004 Filip Navara 00006 * Copyright 2006 CodeWeavers 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include <stdarg.h> 00024 #include <stdio.h> 00025 #include <string.h> 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winerror.h" 00030 #include "winuser.h" 00031 00032 #include "rpc.h" 00033 #include "rpcndr.h" 00034 #include "rpcdcep.h" 00035 00036 #include "wine/debug.h" 00037 00038 #include "rpc_binding.h" 00039 #include "rpc_defs.h" 00040 #include "rpc_message.h" 00041 #include "ncastatus.h" 00042 00043 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 00044 00045 /* note: the DCE/RPC spec says the alignment amount should be 4, but 00046 * MS/RPC servers seem to always use 16 */ 00047 #define AUTH_ALIGNMENT 16 00048 00049 /* gets the amount needed to round a value up to the specified alignment */ 00050 #define ROUND_UP_AMOUNT(value, alignment) \ 00051 (((alignment) - (((value) % (alignment)))) % (alignment)) 00052 #define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) 00053 00054 static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg); 00055 00056 DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) 00057 { 00058 static const DWORD header_sizes[] = { 00059 sizeof(Header->request), 0, sizeof(Header->response), 00060 sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind), 00061 sizeof(Header->bind_ack), sizeof(Header->bind_nack), 00062 0, 0, sizeof(Header->auth3), 0, 0, 0, sizeof(Header->http) 00063 }; 00064 ULONG ret = 0; 00065 00066 if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) { 00067 ret = header_sizes[Header->common.ptype]; 00068 if (ret == 0) 00069 FIXME("unhandled packet type %u\n", Header->common.ptype); 00070 if (Header->common.flags & RPC_FLG_OBJECT_UUID) 00071 ret += sizeof(UUID); 00072 } else { 00073 WARN("invalid packet type %u\n", Header->common.ptype); 00074 } 00075 00076 return ret; 00077 } 00078 00079 static int packet_has_body(const RpcPktHdr *Header) 00080 { 00081 return (Header->common.ptype == PKT_FAULT) || 00082 (Header->common.ptype == PKT_REQUEST) || 00083 (Header->common.ptype == PKT_RESPONSE); 00084 } 00085 00086 static int packet_has_auth_verifier(const RpcPktHdr *Header) 00087 { 00088 return !(Header->common.ptype == PKT_BIND_NACK) && 00089 !(Header->common.ptype == PKT_SHUTDOWN); 00090 } 00091 00092 static int packet_does_auth_negotiation(const RpcPktHdr *Header) 00093 { 00094 switch (Header->common.ptype) 00095 { 00096 case PKT_BIND: 00097 case PKT_BIND_ACK: 00098 case PKT_AUTH3: 00099 case PKT_ALTER_CONTEXT: 00100 case PKT_ALTER_CONTEXT_RESP: 00101 return TRUE; 00102 default: 00103 return FALSE; 00104 } 00105 } 00106 00107 static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, 00108 ULONG DataRepresentation) 00109 { 00110 Header->common.rpc_ver = RPC_VER_MAJOR; 00111 Header->common.rpc_ver_minor = RPC_VER_MINOR; 00112 Header->common.ptype = PacketType; 00113 Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation)); 00114 Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation)); 00115 Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation)); 00116 Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation)); 00117 Header->common.auth_len = 0; 00118 Header->common.call_id = 1; 00119 Header->common.flags = 0; 00120 /* Flags and fragment length are computed in RPCRT4_Send. */ 00121 } 00122 00123 static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation, 00124 ULONG BufferLength, 00125 unsigned short ProcNum, 00126 UUID *ObjectUuid) 00127 { 00128 RpcPktHdr *header; 00129 BOOL has_object; 00130 RPC_STATUS status; 00131 00132 has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status)); 00133 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00134 sizeof(header->request) + (has_object ? sizeof(UUID) : 0)); 00135 if (header == NULL) { 00136 return NULL; 00137 } 00138 00139 RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation); 00140 header->common.frag_len = sizeof(header->request); 00141 header->request.alloc_hint = BufferLength; 00142 header->request.context_id = 0; 00143 header->request.opnum = ProcNum; 00144 if (has_object) { 00145 header->common.flags |= RPC_FLG_OBJECT_UUID; 00146 header->common.frag_len += sizeof(UUID); 00147 memcpy(&header->request + 1, ObjectUuid, sizeof(UUID)); 00148 } 00149 00150 return header; 00151 } 00152 00153 RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength) 00154 { 00155 RpcPktHdr *header; 00156 00157 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response)); 00158 if (header == NULL) { 00159 return NULL; 00160 } 00161 00162 RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation); 00163 header->common.frag_len = sizeof(header->response); 00164 header->response.alloc_hint = BufferLength; 00165 00166 return header; 00167 } 00168 00169 RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status) 00170 { 00171 RpcPktHdr *header; 00172 00173 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault)); 00174 if (header == NULL) { 00175 return NULL; 00176 } 00177 00178 RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation); 00179 header->common.frag_len = sizeof(header->fault); 00180 header->fault.status = Status; 00181 00182 return header; 00183 } 00184 00185 RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, 00186 unsigned short MaxTransmissionSize, 00187 unsigned short MaxReceiveSize, 00188 ULONG AssocGroupId, 00189 const RPC_SYNTAX_IDENTIFIER *AbstractId, 00190 const RPC_SYNTAX_IDENTIFIER *TransferId) 00191 { 00192 RpcPktHdr *header; 00193 RpcContextElement *ctxt_elem; 00194 00195 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00196 sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1])); 00197 if (header == NULL) { 00198 return NULL; 00199 } 00200 ctxt_elem = (RpcContextElement *)(&header->bind + 1); 00201 00202 RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); 00203 header->common.frag_len = sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1]); 00204 header->bind.max_tsize = MaxTransmissionSize; 00205 header->bind.max_rsize = MaxReceiveSize; 00206 header->bind.assoc_gid = AssocGroupId; 00207 header->bind.num_elements = 1; 00208 ctxt_elem->num_syntaxes = 1; 00209 ctxt_elem->abstract_syntax = *AbstractId; 00210 ctxt_elem->transfer_syntaxes[0] = *TransferId; 00211 00212 return header; 00213 } 00214 00215 static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation) 00216 { 00217 RpcPktHdr *header; 00218 00219 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00220 sizeof(header->auth3)); 00221 if (header == NULL) 00222 return NULL; 00223 00224 RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); 00225 header->common.frag_len = sizeof(header->auth3); 00226 00227 return header; 00228 } 00229 00230 RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, 00231 unsigned char RpcVersion, 00232 unsigned char RpcVersionMinor, 00233 unsigned short RejectReason) 00234 { 00235 RpcPktHdr *header; 00236 00237 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1])); 00238 if (header == NULL) { 00239 return NULL; 00240 } 00241 00242 RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); 00243 header->common.frag_len = FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1]); 00244 header->bind_nack.reject_reason = RejectReason; 00245 header->bind_nack.protocols_count = 1; 00246 header->bind_nack.protocols[0].rpc_ver = RpcVersion; 00247 header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; 00248 00249 return header; 00250 } 00251 00252 RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, 00253 unsigned short MaxTransmissionSize, 00254 unsigned short MaxReceiveSize, 00255 ULONG AssocGroupId, 00256 LPCSTR ServerAddress, 00257 unsigned char ResultCount, 00258 const RpcResult *Results) 00259 { 00260 RpcPktHdr *header; 00261 ULONG header_size; 00262 RpcAddressString *server_address; 00263 RpcResultList *results; 00264 00265 header_size = sizeof(header->bind_ack) + 00266 ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + 00267 FIELD_OFFSET(RpcResultList, results[ResultCount]); 00268 00269 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); 00270 if (header == NULL) { 00271 return NULL; 00272 } 00273 00274 RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation); 00275 header->common.frag_len = header_size; 00276 header->bind_ack.max_tsize = MaxTransmissionSize; 00277 header->bind_ack.max_rsize = MaxReceiveSize; 00278 header->bind_ack.assoc_gid = AssocGroupId; 00279 server_address = (RpcAddressString*)(&header->bind_ack + 1); 00280 server_address->length = strlen(ServerAddress) + 1; 00281 strcpy(server_address->string, ServerAddress); 00282 /* results is 4-byte aligned */ 00283 results = (RpcResultList*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); 00284 results->num_results = ResultCount; 00285 memcpy(&results->results[0], Results, ResultCount * sizeof(*Results)); 00286 00287 return header; 00288 } 00289 00290 RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, 00291 unsigned short flags, 00292 unsigned short num_data_items, 00293 unsigned int payload_size) 00294 { 00295 RpcPktHdr *header; 00296 00297 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->http) + payload_size); 00298 if (header == NULL) { 00299 ERR("failed to allocate memory\n"); 00300 return NULL; 00301 } 00302 00303 RPCRT4_BuildCommonHeader(header, PKT_HTTP, DataRepresentation); 00304 /* since the packet isn't current sent using RPCRT4_Send, set the flags 00305 * manually here */ 00306 header->common.flags = RPC_FLG_FIRST|RPC_FLG_LAST; 00307 header->common.call_id = 0; 00308 header->common.frag_len = sizeof(header->http) + payload_size; 00309 header->http.flags = flags; 00310 header->http.num_data_items = num_data_items; 00311 00312 return header; 00313 } 00314 00315 #define WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, type, value) \ 00316 do { \ 00317 *(unsigned int *)(payload) = (type); \ 00318 (payload) += 4; \ 00319 *(unsigned int *)(payload) = (value); \ 00320 (payload) += 4; \ 00321 } while (0) 00322 00323 #define WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, type, uuid) \ 00324 do { \ 00325 *(unsigned int *)(payload) = (type); \ 00326 (payload) += 4; \ 00327 *(UUID *)(payload) = (uuid); \ 00328 (payload) += sizeof(UUID); \ 00329 } while (0) 00330 00331 #define WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, flow_control_increment, uuid) \ 00332 do { \ 00333 *(unsigned int *)(payload) = 0x00000001; \ 00334 (payload) += 4; \ 00335 *(unsigned int *)(payload) = (bytes_transmitted); \ 00336 (payload) += 4; \ 00337 *(unsigned int *)(payload) = (flow_control_increment); \ 00338 (payload) += 4; \ 00339 *(UUID *)(payload) = (uuid); \ 00340 (payload) += sizeof(UUID); \ 00341 } while (0) 00342 00343 RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe, 00344 const UUID *connection_uuid, 00345 const UUID *pipe_uuid, 00346 const UUID *association_uuid) 00347 { 00348 RpcPktHdr *header; 00349 unsigned int size; 00350 char *payload; 00351 00352 size = 8 + 4 + sizeof(UUID) + 4 + sizeof(UUID) + 8; 00353 if (!out_pipe) 00354 size += 8 + 4 + sizeof(UUID); 00355 00356 header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, flags, 00357 out_pipe ? 4 : 6, size); 00358 if (!header) return NULL; 00359 payload = (char *)(&header->http+1); 00360 00361 /* FIXME: what does this part of the payload do? */ 00362 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000006, 0x00000001); 00363 00364 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *connection_uuid); 00365 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *pipe_uuid); 00366 00367 if (out_pipe) 00368 /* FIXME: what does this part of the payload do? */ 00369 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000000, 0x00010000); 00370 else 00371 { 00372 /* FIXME: what does this part of the payload do? */ 00373 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000004, 0x40000000); 00374 /* FIXME: what does this part of the payload do? */ 00375 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000005, 0x000493e0); 00376 00377 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x0000000c, *association_uuid); 00378 } 00379 00380 return header; 00381 } 00382 00383 RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, 00384 ULONG flow_control_increment, 00385 const UUID *pipe_uuid) 00386 { 00387 RpcPktHdr *header; 00388 char *payload; 00389 00390 header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x2, 2, 00391 5 * sizeof(ULONG) + sizeof(UUID)); 00392 if (!header) return NULL; 00393 payload = (char *)(&header->http+1); 00394 00395 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x0000000d, (server ? 0x0 : 0x3)); 00396 00397 WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, 00398 flow_control_increment, *pipe_uuid); 00399 return header; 00400 } 00401 00402 VOID RPCRT4_FreeHeader(RpcPktHdr *Header) 00403 { 00404 HeapFree(GetProcessHeap(), 0, Header); 00405 } 00406 00407 NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status) 00408 { 00409 switch (status) 00410 { 00411 case ERROR_INVALID_HANDLE: return NCA_S_FAULT_CONTEXT_MISMATCH; 00412 case ERROR_OUTOFMEMORY: return NCA_S_FAULT_REMOTE_NO_MEMORY; 00413 case RPC_S_NOT_LISTENING: return NCA_S_SERVER_TOO_BUSY; 00414 case RPC_S_UNKNOWN_IF: return NCA_S_UNK_IF; 00415 case RPC_S_SERVER_TOO_BUSY: return NCA_S_SERVER_TOO_BUSY; 00416 case RPC_S_CALL_FAILED: return NCA_S_FAULT_UNSPEC; 00417 case RPC_S_CALL_FAILED_DNE: return NCA_S_MANAGER_NOT_ENTERED; 00418 case RPC_S_PROTOCOL_ERROR: return NCA_S_PROTO_ERROR; 00419 case RPC_S_UNSUPPORTED_TYPE: return NCA_S_UNSUPPORTED_TYPE; 00420 case RPC_S_INVALID_TAG: return NCA_S_FAULT_INVALID_TAG; 00421 case RPC_S_INVALID_BOUND: return NCA_S_FAULT_INVALID_BOUND; 00422 case RPC_S_PROCNUM_OUT_OF_RANGE: return NCA_S_OP_RNG_ERROR; 00423 case RPC_X_SS_HANDLES_MISMATCH: return NCA_S_FAULT_CONTEXT_MISMATCH; 00424 case RPC_S_CALL_CANCELLED: return NCA_S_FAULT_CANCEL; 00425 case RPC_S_COMM_FAILURE: return NCA_S_COMM_FAILURE; 00426 case RPC_X_WRONG_PIPE_ORDER: return NCA_S_FAULT_PIPE_ORDER; 00427 case RPC_X_PIPE_CLOSED: return NCA_S_FAULT_PIPE_CLOSED; 00428 case RPC_X_PIPE_DISCIPLINE_ERROR: return NCA_S_FAULT_PIPE_DISCIPLINE; 00429 case RPC_X_PIPE_EMPTY: return NCA_S_FAULT_PIPE_EMPTY; 00430 case STATUS_FLOAT_DIVIDE_BY_ZERO: return NCA_S_FAULT_FP_DIV_ZERO; 00431 case STATUS_FLOAT_INVALID_OPERATION: return NCA_S_FAULT_FP_ERROR; 00432 case STATUS_FLOAT_OVERFLOW: return NCA_S_FAULT_FP_OVERFLOW; 00433 case STATUS_FLOAT_UNDERFLOW: return NCA_S_FAULT_FP_UNDERFLOW; 00434 case STATUS_INTEGER_DIVIDE_BY_ZERO: return NCA_S_FAULT_INT_DIV_BY_ZERO; 00435 case STATUS_INTEGER_OVERFLOW: return NCA_S_FAULT_INT_OVERFLOW; 00436 default: return status; 00437 } 00438 } 00439 00440 static RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) 00441 { 00442 switch (status) 00443 { 00444 case NCA_S_COMM_FAILURE: return RPC_S_COMM_FAILURE; 00445 case NCA_S_OP_RNG_ERROR: return RPC_S_PROCNUM_OUT_OF_RANGE; 00446 case NCA_S_UNK_IF: return RPC_S_UNKNOWN_IF; 00447 case NCA_S_YOU_CRASHED: return RPC_S_CALL_FAILED; 00448 case NCA_S_PROTO_ERROR: return RPC_S_PROTOCOL_ERROR; 00449 case NCA_S_OUT_ARGS_TOO_BIG: return ERROR_NOT_ENOUGH_SERVER_MEMORY; 00450 case NCA_S_SERVER_TOO_BUSY: return RPC_S_SERVER_TOO_BUSY; 00451 case NCA_S_UNSUPPORTED_TYPE: return RPC_S_UNSUPPORTED_TYPE; 00452 case NCA_S_FAULT_INT_DIV_BY_ZERO: return RPC_S_ZERO_DIVIDE; 00453 case NCA_S_FAULT_ADDR_ERROR: return RPC_S_ADDRESS_ERROR; 00454 case NCA_S_FAULT_FP_DIV_ZERO: return RPC_S_FP_DIV_ZERO; 00455 case NCA_S_FAULT_FP_UNDERFLOW: return RPC_S_FP_UNDERFLOW; 00456 case NCA_S_FAULT_FP_OVERFLOW: return RPC_S_FP_OVERFLOW; 00457 case NCA_S_FAULT_INVALID_TAG: return RPC_S_INVALID_TAG; 00458 case NCA_S_FAULT_INVALID_BOUND: return RPC_S_INVALID_BOUND; 00459 case NCA_S_RPC_VERSION_MISMATCH: return RPC_S_PROTOCOL_ERROR; 00460 case NCA_S_UNSPEC_REJECT: return RPC_S_CALL_FAILED_DNE; 00461 case NCA_S_BAD_ACTID: return RPC_S_CALL_FAILED_DNE; 00462 case NCA_S_WHO_ARE_YOU_FAILED: return RPC_S_CALL_FAILED; 00463 case NCA_S_MANAGER_NOT_ENTERED: return RPC_S_CALL_FAILED_DNE; 00464 case NCA_S_FAULT_CANCEL: return RPC_S_CALL_CANCELLED; 00465 case NCA_S_FAULT_ILL_INST: return RPC_S_ADDRESS_ERROR; 00466 case NCA_S_FAULT_FP_ERROR: return RPC_S_FP_OVERFLOW; 00467 case NCA_S_FAULT_INT_OVERFLOW: return RPC_S_ADDRESS_ERROR; 00468 case NCA_S_FAULT_UNSPEC: return RPC_S_CALL_FAILED; 00469 case NCA_S_FAULT_PIPE_EMPTY: return RPC_X_PIPE_EMPTY; 00470 case NCA_S_FAULT_PIPE_CLOSED: return RPC_X_PIPE_CLOSED; 00471 case NCA_S_FAULT_PIPE_ORDER: return RPC_X_WRONG_PIPE_ORDER; 00472 case NCA_S_FAULT_PIPE_DISCIPLINE: return RPC_X_PIPE_DISCIPLINE_ERROR; 00473 case NCA_S_FAULT_PIPE_COMM_ERROR: return RPC_S_COMM_FAILURE; 00474 case NCA_S_FAULT_PIPE_MEMORY: return ERROR_OUTOFMEMORY; 00475 case NCA_S_FAULT_CONTEXT_MISMATCH: return ERROR_INVALID_HANDLE; 00476 case NCA_S_FAULT_REMOTE_NO_MEMORY: return ERROR_NOT_ENOUGH_SERVER_MEMORY; 00477 default: return status; 00478 } 00479 } 00480 00481 /* assumes the common header fields have already been validated */ 00482 BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, 00483 unsigned short data_len) 00484 { 00485 unsigned short i; 00486 BYTE *p = data; 00487 00488 for (i = 0; i < hdr->http.num_data_items; i++) 00489 { 00490 ULONG type; 00491 00492 if (data_len < sizeof(ULONG)) 00493 return FALSE; 00494 00495 type = *(ULONG *)p; 00496 p += sizeof(ULONG); 00497 data_len -= sizeof(ULONG); 00498 00499 switch (type) 00500 { 00501 case 0x3: 00502 case 0xc: 00503 if (data_len < sizeof(GUID)) 00504 return FALSE; 00505 p += sizeof(GUID); 00506 data_len -= sizeof(GUID); 00507 break; 00508 case 0x0: 00509 case 0x2: 00510 case 0x4: 00511 case 0x5: 00512 case 0x6: 00513 case 0xd: 00514 if (data_len < sizeof(ULONG)) 00515 return FALSE; 00516 p += sizeof(ULONG); 00517 data_len -= sizeof(ULONG); 00518 break; 00519 case 0x1: 00520 if (data_len < 24) 00521 return FALSE; 00522 p += 24; 00523 data_len -= 24; 00524 break; 00525 default: 00526 FIXME("unimplemented type 0x%x\n", type); 00527 break; 00528 } 00529 } 00530 return TRUE; 00531 } 00532 00533 /* assumes the HTTP packet has been validated */ 00534 static unsigned char *RPCRT4_NextHttpHeaderField(unsigned char *data) 00535 { 00536 ULONG type; 00537 00538 type = *(ULONG *)data; 00539 data += sizeof(ULONG); 00540 00541 switch (type) 00542 { 00543 case 0x3: 00544 case 0xc: 00545 return data + sizeof(GUID); 00546 case 0x0: 00547 case 0x2: 00548 case 0x4: 00549 case 0x5: 00550 case 0x6: 00551 case 0xd: 00552 return data + sizeof(ULONG); 00553 case 0x1: 00554 return data + 24; 00555 default: 00556 FIXME("unimplemented type 0x%x\n", type); 00557 return data; 00558 } 00559 } 00560 00561 #define READ_HTTP_PAYLOAD_FIELD_TYPE(data) *(ULONG *)(data) 00562 #define GET_HTTP_PAYLOAD_FIELD_DATA(data) ((data) + sizeof(ULONG)) 00563 00564 /* assumes the HTTP packet has been validated */ 00565 RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, 00566 unsigned char *data, ULONG *field1) 00567 { 00568 ULONG type; 00569 if (header->http.flags != 0x0) 00570 { 00571 ERR("invalid flags 0x%x\n", header->http.flags); 00572 return RPC_S_PROTOCOL_ERROR; 00573 } 00574 if (header->http.num_data_items != 1) 00575 { 00576 ERR("invalid number of data items %d\n", header->http.num_data_items); 00577 return RPC_S_PROTOCOL_ERROR; 00578 } 00579 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00580 if (type != 0x00000002) 00581 { 00582 ERR("invalid type 0x%08x\n", type); 00583 return RPC_S_PROTOCOL_ERROR; 00584 } 00585 *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 00586 return RPC_S_OK; 00587 } 00588 00589 /* assumes the HTTP packet has been validated */ 00590 RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, 00591 unsigned char *data, ULONG *field1, 00592 ULONG *bytes_until_next_packet, 00593 ULONG *field3) 00594 { 00595 ULONG type; 00596 if (header->http.flags != 0x0) 00597 { 00598 ERR("invalid flags 0x%x\n", header->http.flags); 00599 return RPC_S_PROTOCOL_ERROR; 00600 } 00601 if (header->http.num_data_items != 3) 00602 { 00603 ERR("invalid number of data items %d\n", header->http.num_data_items); 00604 return RPC_S_PROTOCOL_ERROR; 00605 } 00606 00607 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00608 if (type != 0x00000006) 00609 { 00610 ERR("invalid type for field 1: 0x%08x\n", type); 00611 return RPC_S_PROTOCOL_ERROR; 00612 } 00613 *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 00614 data = RPCRT4_NextHttpHeaderField(data); 00615 00616 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00617 if (type != 0x00000000) 00618 { 00619 ERR("invalid type for field 2: 0x%08x\n", type); 00620 return RPC_S_PROTOCOL_ERROR; 00621 } 00622 *bytes_until_next_packet = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 00623 data = RPCRT4_NextHttpHeaderField(data); 00624 00625 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00626 if (type != 0x00000002) 00627 { 00628 ERR("invalid type for field 3: 0x%08x\n", type); 00629 return RPC_S_PROTOCOL_ERROR; 00630 } 00631 *field3 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 00632 00633 return RPC_S_OK; 00634 } 00635 00636 RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, 00637 unsigned char *data, BOOL server, 00638 ULONG *bytes_transmitted, 00639 ULONG *flow_control_increment, 00640 UUID *pipe_uuid) 00641 { 00642 ULONG type; 00643 if (header->http.flags != 0x2) 00644 { 00645 ERR("invalid flags 0x%x\n", header->http.flags); 00646 return RPC_S_PROTOCOL_ERROR; 00647 } 00648 if (header->http.num_data_items != 2) 00649 { 00650 ERR("invalid number of data items %d\n", header->http.num_data_items); 00651 return RPC_S_PROTOCOL_ERROR; 00652 } 00653 00654 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00655 if (type != 0x0000000d) 00656 { 00657 ERR("invalid type for field 1: 0x%08x\n", type); 00658 return RPC_S_PROTOCOL_ERROR; 00659 } 00660 if (*(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data) != (server ? 0x3 : 0x0)) 00661 { 00662 ERR("invalid type for 0xd field data: 0x%08x\n", *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data)); 00663 return RPC_S_PROTOCOL_ERROR; 00664 } 00665 data = RPCRT4_NextHttpHeaderField(data); 00666 00667 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 00668 if (type != 0x00000001) 00669 { 00670 ERR("invalid type for field 2: 0x%08x\n", type); 00671 return RPC_S_PROTOCOL_ERROR; 00672 } 00673 *bytes_transmitted = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 00674 *flow_control_increment = *(ULONG *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 4); 00675 *pipe_uuid = *(UUID *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 8); 00676 00677 return RPC_S_OK; 00678 } 00679 00680 00681 RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection, 00682 enum secure_packet_direction dir, 00683 RpcPktHdr *hdr, unsigned int hdr_size, 00684 unsigned char *stub_data, unsigned int stub_data_size, 00685 RpcAuthVerifier *auth_hdr, 00686 unsigned char *auth_value, unsigned int auth_value_size) 00687 { 00688 SecBufferDesc message; 00689 SecBuffer buffers[4]; 00690 SECURITY_STATUS sec_status; 00691 00692 message.ulVersion = SECBUFFER_VERSION; 00693 message.cBuffers = sizeof(buffers)/sizeof(buffers[0]); 00694 message.pBuffers = buffers; 00695 00696 buffers[0].cbBuffer = hdr_size; 00697 buffers[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; 00698 buffers[0].pvBuffer = hdr; 00699 buffers[1].cbBuffer = stub_data_size; 00700 buffers[1].BufferType = SECBUFFER_DATA; 00701 buffers[1].pvBuffer = stub_data; 00702 buffers[2].cbBuffer = sizeof(*auth_hdr); 00703 buffers[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; 00704 buffers[2].pvBuffer = auth_hdr; 00705 buffers[3].cbBuffer = auth_value_size; 00706 buffers[3].BufferType = SECBUFFER_TOKEN; 00707 buffers[3].pvBuffer = auth_value; 00708 00709 if (dir == SECURE_PACKET_SEND) 00710 { 00711 if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) 00712 { 00713 sec_status = EncryptMessage(&Connection->ctx, 0, &message, 0 /* FIXME */); 00714 if (sec_status != SEC_E_OK) 00715 { 00716 ERR("EncryptMessage failed with 0x%08x\n", sec_status); 00717 return RPC_S_SEC_PKG_ERROR; 00718 } 00719 } 00720 else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) 00721 { 00722 sec_status = MakeSignature(&Connection->ctx, 0, &message, 0 /* FIXME */); 00723 if (sec_status != SEC_E_OK) 00724 { 00725 ERR("MakeSignature failed with 0x%08x\n", sec_status); 00726 return RPC_S_SEC_PKG_ERROR; 00727 } 00728 } 00729 } 00730 else if (dir == SECURE_PACKET_RECEIVE) 00731 { 00732 if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) 00733 { 00734 sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); 00735 if (sec_status != SEC_E_OK) 00736 { 00737 ERR("DecryptMessage failed with 0x%08x\n", sec_status); 00738 return RPC_S_SEC_PKG_ERROR; 00739 } 00740 } 00741 else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) 00742 { 00743 sec_status = VerifySignature(&Connection->ctx, &message, 0 /* FIXME */, NULL); 00744 if (sec_status != SEC_E_OK) 00745 { 00746 ERR("VerifySignature failed with 0x%08x\n", sec_status); 00747 return RPC_S_SEC_PKG_ERROR; 00748 } 00749 } 00750 } 00751 00752 return RPC_S_OK; 00753 } 00754 00755 /*********************************************************************** 00756 * RPCRT4_SendWithAuth (internal) 00757 * 00758 * Transmit a packet with authorization data over connection in acceptable fragments. 00759 */ 00760 RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, 00761 void *Buffer, unsigned int BufferLength, 00762 const void *Auth, unsigned int AuthLength) 00763 { 00764 PUCHAR buffer_pos; 00765 DWORD hdr_size; 00766 LONG count; 00767 unsigned char *pkt; 00768 LONG alen; 00769 RPC_STATUS status; 00770 00771 RPCRT4_SetThreadCurrentConnection(Connection); 00772 00773 buffer_pos = Buffer; 00774 /* The packet building functions save the packet header size, so we can use it. */ 00775 hdr_size = Header->common.frag_len; 00776 if (AuthLength) 00777 Header->common.auth_len = AuthLength; 00778 else if (Connection->AuthInfo && packet_has_auth_verifier(Header)) 00779 { 00780 if ((Connection->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(Header)) 00781 Header->common.auth_len = Connection->encryption_auth_len; 00782 else 00783 Header->common.auth_len = Connection->signature_auth_len; 00784 } 00785 else 00786 Header->common.auth_len = 0; 00787 Header->common.flags |= RPC_FLG_FIRST; 00788 Header->common.flags &= ~RPC_FLG_LAST; 00789 00790 alen = RPC_AUTH_VERIFIER_LEN(&Header->common); 00791 00792 while (!(Header->common.flags & RPC_FLG_LAST)) { 00793 unsigned char auth_pad_len = Header->common.auth_len ? ROUND_UP_AMOUNT(BufferLength, AUTH_ALIGNMENT) : 0; 00794 unsigned int pkt_size = BufferLength + hdr_size + alen + auth_pad_len; 00795 00796 /* decide if we need to split the packet into fragments */ 00797 if (pkt_size <= Connection->MaxTransmissionSize) { 00798 Header->common.flags |= RPC_FLG_LAST; 00799 Header->common.frag_len = pkt_size; 00800 } else { 00801 auth_pad_len = 0; 00802 /* make sure packet payload will be a multiple of 16 */ 00803 Header->common.frag_len = 00804 ((Connection->MaxTransmissionSize - hdr_size - alen) & ~(AUTH_ALIGNMENT-1)) + 00805 hdr_size + alen; 00806 } 00807 00808 pkt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Header->common.frag_len); 00809 00810 memcpy(pkt, Header, hdr_size); 00811 00812 /* fragment consisted of header only and is the last one */ 00813 if (hdr_size == Header->common.frag_len) 00814 goto write; 00815 00816 memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - auth_pad_len - alen); 00817 00818 /* add the authorization info */ 00819 if (Header->common.auth_len) 00820 { 00821 RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; 00822 00823 auth_hdr->auth_type = Connection->AuthInfo->AuthnSvc; 00824 auth_hdr->auth_level = Connection->AuthInfo->AuthnLevel; 00825 auth_hdr->auth_pad_length = auth_pad_len; 00826 auth_hdr->auth_reserved = 0; 00827 /* a unique number... */ 00828 auth_hdr->auth_context_id = Connection->auth_context_id; 00829 00830 if (AuthLength) 00831 memcpy(auth_hdr + 1, Auth, AuthLength); 00832 else 00833 { 00834 status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_SEND, 00835 (RpcPktHdr *)pkt, hdr_size, 00836 pkt + hdr_size, Header->common.frag_len - hdr_size - alen, 00837 auth_hdr, 00838 (unsigned char *)(auth_hdr + 1), Header->common.auth_len); 00839 if (status != RPC_S_OK) 00840 { 00841 HeapFree(GetProcessHeap(), 0, pkt); 00842 RPCRT4_SetThreadCurrentConnection(NULL); 00843 return status; 00844 } 00845 } 00846 } 00847 00848 write: 00849 count = rpcrt4_conn_write(Connection, pkt, Header->common.frag_len); 00850 HeapFree(GetProcessHeap(), 0, pkt); 00851 if (count<0) { 00852 WARN("rpcrt4_conn_write failed (auth)\n"); 00853 RPCRT4_SetThreadCurrentConnection(NULL); 00854 return RPC_S_CALL_FAILED; 00855 } 00856 00857 buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; 00858 BufferLength -= Header->common.frag_len - hdr_size - alen - auth_pad_len; 00859 Header->common.flags &= ~RPC_FLG_FIRST; 00860 } 00861 00862 RPCRT4_SetThreadCurrentConnection(NULL); 00863 return RPC_S_OK; 00864 } 00865 00866 /*********************************************************************** 00867 * RPCRT4_default_authorize (internal) 00868 * 00869 * Authorize a client connection. 00870 */ 00871 RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, 00872 unsigned char *in_buffer, 00873 unsigned int in_size, 00874 unsigned char *out_buffer, 00875 unsigned int *out_size) 00876 { 00877 SECURITY_STATUS r; 00878 SecBufferDesc out_desc; 00879 SecBufferDesc inp_desc; 00880 SecPkgContext_Sizes secctx_sizes; 00881 BOOL continue_needed; 00882 ULONG context_req; 00883 SecBuffer in, out; 00884 00885 if (!out_buffer) 00886 { 00887 *out_size = conn->AuthInfo->cbMaxToken; 00888 return RPC_S_OK; 00889 } 00890 00891 in.BufferType = SECBUFFER_TOKEN; 00892 in.pvBuffer = in_buffer; 00893 in.cbBuffer = in_size; 00894 00895 out.BufferType = SECBUFFER_TOKEN; 00896 out.pvBuffer = out_buffer; 00897 out.cbBuffer = *out_size; 00898 00899 out_desc.ulVersion = 0; 00900 out_desc.cBuffers = 1; 00901 out_desc.pBuffers = &out; 00902 00903 inp_desc.ulVersion = 0; 00904 inp_desc.cBuffers = 1; 00905 inp_desc.pBuffers = ∈ 00906 00907 if (conn->server) 00908 { 00909 context_req = ASC_REQ_CONNECTION | ASC_REQ_USE_DCE_STYLE | 00910 ASC_REQ_DELEGATE; 00911 00912 if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) 00913 context_req |= ASC_REQ_INTEGRITY; 00914 else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 00915 context_req |= ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY; 00916 00917 r = AcceptSecurityContext(&conn->AuthInfo->cred, 00918 first_time ? NULL : &conn->ctx, 00919 &inp_desc, context_req, SECURITY_NETWORK_DREP, 00920 &conn->ctx, 00921 &out_desc, &conn->attr, &conn->exp); 00922 if (r == SEC_E_OK || r == SEC_I_COMPLETE_NEEDED) 00923 { 00924 /* authorisation done, so nothing more to send */ 00925 out.cbBuffer = 0; 00926 } 00927 } 00928 else 00929 { 00930 context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | 00931 ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; 00932 00933 if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) 00934 context_req |= ISC_REQ_INTEGRITY; 00935 else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 00936 context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; 00937 00938 r = InitializeSecurityContextW(&conn->AuthInfo->cred, 00939 first_time ? NULL: &conn->ctx, 00940 first_time ? conn->AuthInfo->server_principal_name : NULL, 00941 context_req, 0, SECURITY_NETWORK_DREP, 00942 first_time ? NULL : &inp_desc, 0, &conn->ctx, 00943 &out_desc, &conn->attr, &conn->exp); 00944 } 00945 if (FAILED(r)) 00946 { 00947 WARN("InitializeSecurityContext failed with error 0x%08x\n", r); 00948 goto failed; 00949 } 00950 00951 TRACE("r = 0x%08x, attr = 0x%08x\n", r, conn->attr); 00952 continue_needed = ((r == SEC_I_CONTINUE_NEEDED) || 00953 (r == SEC_I_COMPLETE_AND_CONTINUE)); 00954 00955 if ((r == SEC_I_COMPLETE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)) 00956 { 00957 TRACE("complete needed\n"); 00958 r = CompleteAuthToken(&conn->ctx, &out_desc); 00959 if (FAILED(r)) 00960 { 00961 WARN("CompleteAuthToken failed with error 0x%08x\n", r); 00962 goto failed; 00963 } 00964 } 00965 00966 TRACE("cbBuffer = %d\n", out.cbBuffer); 00967 00968 if (!continue_needed) 00969 { 00970 r = QueryContextAttributesA(&conn->ctx, SECPKG_ATTR_SIZES, &secctx_sizes); 00971 if (FAILED(r)) 00972 { 00973 WARN("QueryContextAttributes failed with error 0x%08x\n", r); 00974 goto failed; 00975 } 00976 conn->signature_auth_len = secctx_sizes.cbMaxSignature; 00977 conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; 00978 } 00979 00980 *out_size = out.cbBuffer; 00981 return RPC_S_OK; 00982 00983 failed: 00984 *out_size = 0; 00985 return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ 00986 } 00987 00988 /*********************************************************************** 00989 * RPCRT4_ClientConnectionAuth (internal) 00990 */ 00991 RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, 00992 ULONG count) 00993 { 00994 RpcPktHdr *resp_hdr; 00995 RPC_STATUS status; 00996 unsigned char *out_buffer; 00997 unsigned int out_len = 0; 00998 00999 TRACE("challenge %s, %d bytes\n", challenge, count); 01000 01001 status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, NULL, &out_len); 01002 if (status) return status; 01003 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_len); 01004 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 01005 status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, out_buffer, &out_len); 01006 if (status) return status; 01007 01008 resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); 01009 01010 if (resp_hdr) 01011 status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out_buffer, out_len); 01012 else 01013 status = RPC_S_OUT_OF_RESOURCES; 01014 01015 HeapFree(GetProcessHeap(), 0, out_buffer); 01016 RPCRT4_FreeHeader(resp_hdr); 01017 01018 return status; 01019 } 01020 01021 /*********************************************************************** 01022 * RPCRT4_ServerConnectionAuth (internal) 01023 */ 01024 RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, 01025 BOOL start, 01026 RpcAuthVerifier *auth_data_in, 01027 ULONG auth_length_in, 01028 unsigned char **auth_data_out, 01029 ULONG *auth_length_out) 01030 { 01031 unsigned char *out_buffer; 01032 unsigned int out_size; 01033 RPC_STATUS status; 01034 01035 if (start) 01036 { 01037 /* remove any existing authentication information */ 01038 if (conn->AuthInfo) 01039 { 01040 RpcAuthInfo_Release(conn->AuthInfo); 01041 conn->AuthInfo = NULL; 01042 } 01043 if (SecIsValidHandle(&conn->ctx)) 01044 { 01045 DeleteSecurityContext(&conn->ctx); 01046 SecInvalidateHandle(&conn->ctx); 01047 } 01048 if (auth_length_in >= sizeof(RpcAuthVerifier)) 01049 { 01050 CredHandle cred; 01051 TimeStamp exp; 01052 ULONG max_token; 01053 01054 status = RPCRT4_ServerGetRegisteredAuthInfo( 01055 auth_data_in->auth_type, &cred, &exp, &max_token); 01056 if (status != RPC_S_OK) 01057 { 01058 ERR("unknown authentication service %u\n", auth_data_in->auth_type); 01059 return status; 01060 } 01061 01062 status = RpcAuthInfo_Create(auth_data_in->auth_level, 01063 auth_data_in->auth_type, cred, exp, 01064 max_token, NULL, &conn->AuthInfo); 01065 if (status != RPC_S_OK) 01066 return status; 01067 01068 /* FIXME: should auth_data_in->auth_context_id be checked in the !start case? */ 01069 conn->auth_context_id = auth_data_in->auth_context_id; 01070 } 01071 } 01072 01073 if (auth_length_in < sizeof(RpcAuthVerifier)) 01074 return RPC_S_OK; 01075 01076 if (!conn->AuthInfo) 01077 /* should have filled in authentication info by now */ 01078 return RPC_S_PROTOCOL_ERROR; 01079 01080 status = rpcrt4_conn_authorize( 01081 conn, start, (unsigned char *)(auth_data_in + 1), 01082 auth_length_in - sizeof(RpcAuthVerifier), NULL, &out_size); 01083 if (status) return status; 01084 01085 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); 01086 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 01087 01088 status = rpcrt4_conn_authorize( 01089 conn, start, (unsigned char *)(auth_data_in + 1), 01090 auth_length_in - sizeof(RpcAuthVerifier), out_buffer, &out_size); 01091 if (status != RPC_S_OK) 01092 { 01093 HeapFree(GetProcessHeap(), 0, out_buffer); 01094 return status; 01095 } 01096 01097 if (out_size && !auth_length_out) 01098 { 01099 ERR("expected authentication to be complete but SSP returned data of " 01100 "%u bytes to be sent back to client\n", out_size); 01101 HeapFree(GetProcessHeap(), 0, out_buffer); 01102 return RPC_S_SEC_PKG_ERROR; 01103 } 01104 else 01105 { 01106 *auth_data_out = out_buffer; 01107 *auth_length_out = out_size; 01108 } 01109 01110 return status; 01111 } 01112 01113 /*********************************************************************** 01114 * RPCRT4_default_is_authorized (internal) 01115 * 01116 * Has a connection started the process of authorizing with the server? 01117 */ 01118 BOOL RPCRT4_default_is_authorized(RpcConnection *Connection) 01119 { 01120 return Connection->AuthInfo && SecIsValidHandle(&Connection->ctx); 01121 } 01122 01123 /*********************************************************************** 01124 * RPCRT4_default_impersonate_client (internal) 01125 * 01126 */ 01127 RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn) 01128 { 01129 SECURITY_STATUS sec_status; 01130 01131 TRACE("(%p)\n", conn); 01132 01133 if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) 01134 return RPC_S_NO_CONTEXT_AVAILABLE; 01135 sec_status = ImpersonateSecurityContext(&conn->ctx); 01136 if (sec_status != SEC_E_OK) 01137 WARN("ImpersonateSecurityContext returned 0x%08x\n", sec_status); 01138 switch (sec_status) 01139 { 01140 case SEC_E_UNSUPPORTED_FUNCTION: 01141 return RPC_S_CANNOT_SUPPORT; 01142 case SEC_E_NO_IMPERSONATION: 01143 return RPC_S_NO_CONTEXT_AVAILABLE; 01144 case SEC_E_OK: 01145 return RPC_S_OK; 01146 default: 01147 return RPC_S_SEC_PKG_ERROR; 01148 } 01149 } 01150 01151 /*********************************************************************** 01152 * RPCRT4_default_revert_to_self (internal) 01153 * 01154 */ 01155 RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn) 01156 { 01157 SECURITY_STATUS sec_status; 01158 01159 TRACE("(%p)\n", conn); 01160 01161 if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) 01162 return RPC_S_NO_CONTEXT_AVAILABLE; 01163 sec_status = RevertSecurityContext(&conn->ctx); 01164 if (sec_status != SEC_E_OK) 01165 WARN("RevertSecurityContext returned 0x%08x\n", sec_status); 01166 switch (sec_status) 01167 { 01168 case SEC_E_UNSUPPORTED_FUNCTION: 01169 return RPC_S_CANNOT_SUPPORT; 01170 case SEC_E_NO_IMPERSONATION: 01171 return RPC_S_NO_CONTEXT_AVAILABLE; 01172 case SEC_E_OK: 01173 return RPC_S_OK; 01174 default: 01175 return RPC_S_SEC_PKG_ERROR; 01176 } 01177 } 01178 01179 /*********************************************************************** 01180 * RPCRT4_default_inquire_auth_client (internal) 01181 * 01182 * Default function to retrieve the authentication details that the client 01183 * is using to call the server. 01184 */ 01185 RPC_STATUS RPCRT4_default_inquire_auth_client( 01186 RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, 01187 ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) 01188 { 01189 if (!conn->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; 01190 01191 if (privs) 01192 { 01193 FIXME("privs not implemented\n"); 01194 *privs = NULL; 01195 } 01196 if (server_princ_name) 01197 { 01198 *server_princ_name = RPCRT4_strdupW(conn->AuthInfo->server_principal_name); 01199 if (!*server_princ_name) return ERROR_OUTOFMEMORY; 01200 } 01201 if (authn_level) *authn_level = conn->AuthInfo->AuthnLevel; 01202 if (authn_svc) *authn_svc = conn->AuthInfo->AuthnSvc; 01203 if (authz_svc) 01204 { 01205 FIXME("authorization service not implemented\n"); 01206 *authz_svc = RPC_C_AUTHZ_NONE; 01207 } 01208 if (flags) 01209 FIXME("flags 0x%x not implemented\n", flags); 01210 01211 return RPC_S_OK; 01212 } 01213 01214 /*********************************************************************** 01215 * RPCRT4_Send (internal) 01216 * 01217 * Transmit a packet over connection in acceptable fragments. 01218 */ 01219 RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, 01220 void *Buffer, unsigned int BufferLength) 01221 { 01222 RPC_STATUS r; 01223 01224 if (packet_does_auth_negotiation(Header) && 01225 Connection->AuthInfo && 01226 !rpcrt4_conn_is_authorized(Connection)) 01227 { 01228 unsigned int out_size = 0; 01229 unsigned char *out_buffer; 01230 01231 r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, NULL, &out_size); 01232 if (r != RPC_S_OK) return r; 01233 01234 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); 01235 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 01236 01237 /* tack on a negotiate packet */ 01238 r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, out_buffer, &out_size); 01239 if (r == RPC_S_OK) 01240 r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out_buffer, out_size); 01241 01242 HeapFree(GetProcessHeap(), 0, out_buffer); 01243 } 01244 else 01245 r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); 01246 01247 return r; 01248 } 01249 01250 /* validates version and frag_len fields */ 01251 RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) 01252 { 01253 DWORD hdr_length; 01254 01255 /* verify if the header really makes sense */ 01256 if (hdr->rpc_ver != RPC_VER_MAJOR || 01257 hdr->rpc_ver_minor != RPC_VER_MINOR) 01258 { 01259 WARN("unhandled packet version\n"); 01260 return RPC_S_PROTOCOL_ERROR; 01261 } 01262 01263 hdr_length = RPCRT4_GetHeaderSize((const RpcPktHdr*)hdr); 01264 if (hdr_length == 0) 01265 { 01266 WARN("header length == 0\n"); 01267 return RPC_S_PROTOCOL_ERROR; 01268 } 01269 01270 if (hdr->frag_len < hdr_length) 01271 { 01272 WARN("bad frag length %d\n", hdr->frag_len); 01273 return RPC_S_PROTOCOL_ERROR; 01274 } 01275 01276 return RPC_S_OK; 01277 } 01278 01279 /*********************************************************************** 01280 * RPCRT4_default_receive_fragment (internal) 01281 * 01282 * Receive a fragment from a connection. 01283 */ 01284 static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 01285 { 01286 RPC_STATUS status; 01287 DWORD hdr_length; 01288 LONG dwRead; 01289 RpcPktCommonHdr common_hdr; 01290 01291 *Header = NULL; 01292 *Payload = NULL; 01293 01294 TRACE("(%p, %p, %p)\n", Connection, Header, Payload); 01295 01296 /* read packet common header */ 01297 dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); 01298 if (dwRead != sizeof(common_hdr)) { 01299 WARN("Short read of header, %d bytes\n", dwRead); 01300 status = RPC_S_CALL_FAILED; 01301 goto fail; 01302 } 01303 01304 status = RPCRT4_ValidateCommonHeader(&common_hdr); 01305 if (status != RPC_S_OK) goto fail; 01306 01307 hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); 01308 if (hdr_length == 0) { 01309 WARN("header length == 0\n"); 01310 status = RPC_S_PROTOCOL_ERROR; 01311 goto fail; 01312 } 01313 01314 *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); 01315 memcpy(*Header, &common_hdr, sizeof(common_hdr)); 01316 01317 /* read the rest of packet header */ 01318 dwRead = rpcrt4_conn_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); 01319 if (dwRead != hdr_length - sizeof(common_hdr)) { 01320 WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); 01321 status = RPC_S_CALL_FAILED; 01322 goto fail; 01323 } 01324 01325 if (common_hdr.frag_len - hdr_length) 01326 { 01327 *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length); 01328 if (!*Payload) 01329 { 01330 status = RPC_S_OUT_OF_RESOURCES; 01331 goto fail; 01332 } 01333 01334 dwRead = rpcrt4_conn_read(Connection, *Payload, common_hdr.frag_len - hdr_length); 01335 if (dwRead != common_hdr.frag_len - hdr_length) 01336 { 01337 WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length); 01338 status = RPC_S_CALL_FAILED; 01339 goto fail; 01340 } 01341 } 01342 else 01343 *Payload = NULL; 01344 01345 /* success */ 01346 status = RPC_S_OK; 01347 01348 fail: 01349 if (status != RPC_S_OK) { 01350 RPCRT4_FreeHeader(*Header); 01351 *Header = NULL; 01352 HeapFree(GetProcessHeap(), 0, *Payload); 01353 *Payload = NULL; 01354 } 01355 return status; 01356 } 01357 01358 static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 01359 { 01360 if (Connection->ops->receive_fragment) 01361 return Connection->ops->receive_fragment(Connection, Header, Payload); 01362 else 01363 return RPCRT4_default_receive_fragment(Connection, Header, Payload); 01364 } 01365 01366 /*********************************************************************** 01367 * RPCRT4_ReceiveWithAuth (internal) 01368 * 01369 * Receive a packet from connection, merge the fragments and return the auth 01370 * data. 01371 */ 01372 RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, 01373 PRPC_MESSAGE pMsg, 01374 unsigned char **auth_data_out, 01375 ULONG *auth_length_out) 01376 { 01377 RPC_STATUS status; 01378 DWORD hdr_length; 01379 unsigned short first_flag; 01380 ULONG data_length; 01381 ULONG buffer_length; 01382 ULONG auth_length = 0; 01383 unsigned char *auth_data = NULL; 01384 RpcPktHdr *CurrentHeader = NULL; 01385 void *payload = NULL; 01386 01387 *Header = NULL; 01388 pMsg->Buffer = NULL; 01389 if (auth_data_out) *auth_data_out = NULL; 01390 if (auth_length_out) *auth_length_out = 0; 01391 01392 TRACE("(%p, %p, %p, %p)\n", Connection, Header, pMsg, auth_data_out); 01393 01394 RPCRT4_SetThreadCurrentConnection(Connection); 01395 01396 status = RPCRT4_receive_fragment(Connection, Header, &payload); 01397 if (status != RPC_S_OK) goto fail; 01398 01399 hdr_length = RPCRT4_GetHeaderSize(*Header); 01400 01401 /* read packet body */ 01402 switch ((*Header)->common.ptype) { 01403 case PKT_RESPONSE: 01404 pMsg->BufferLength = (*Header)->response.alloc_hint; 01405 break; 01406 case PKT_REQUEST: 01407 pMsg->BufferLength = (*Header)->request.alloc_hint; 01408 break; 01409 default: 01410 pMsg->BufferLength = (*Header)->common.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&(*Header)->common); 01411 } 01412 01413 TRACE("buffer length = %u\n", pMsg->BufferLength); 01414 01415 pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength); 01416 if (!pMsg->Buffer) 01417 { 01418 status = ERROR_OUTOFMEMORY; 01419 goto fail; 01420 } 01421 01422 first_flag = RPC_FLG_FIRST; 01423 auth_length = (*Header)->common.auth_len; 01424 if (auth_length) { 01425 auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&(*Header)->common)); 01426 if (!auth_data) { 01427 status = RPC_S_OUT_OF_RESOURCES; 01428 goto fail; 01429 } 01430 } 01431 CurrentHeader = *Header; 01432 buffer_length = 0; 01433 while (TRUE) 01434 { 01435 unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&CurrentHeader->common); 01436 01437 /* verify header fields */ 01438 01439 if ((CurrentHeader->common.frag_len < hdr_length) || 01440 (CurrentHeader->common.frag_len - hdr_length < header_auth_len)) { 01441 WARN("frag_len %d too small for hdr_length %d and auth_len %d\n", 01442 CurrentHeader->common.frag_len, hdr_length, CurrentHeader->common.auth_len); 01443 status = RPC_S_PROTOCOL_ERROR; 01444 goto fail; 01445 } 01446 01447 if (CurrentHeader->common.auth_len != auth_length) { 01448 WARN("auth_len header field changed from %d to %d\n", 01449 auth_length, CurrentHeader->common.auth_len); 01450 status = RPC_S_PROTOCOL_ERROR; 01451 goto fail; 01452 } 01453 01454 if ((CurrentHeader->common.flags & RPC_FLG_FIRST) != first_flag) { 01455 TRACE("invalid packet flags\n"); 01456 status = RPC_S_PROTOCOL_ERROR; 01457 goto fail; 01458 } 01459 01460 data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len; 01461 if (data_length + buffer_length > pMsg->BufferLength) { 01462 TRACE("allocation hint exceeded, new buffer length = %d\n", 01463 data_length + buffer_length); 01464 pMsg->BufferLength = data_length + buffer_length; 01465 status = I_RpcReAllocateBuffer(pMsg); 01466 if (status != RPC_S_OK) goto fail; 01467 } 01468 01469 memcpy((unsigned char *)pMsg->Buffer + buffer_length, payload, data_length); 01470 01471 if (header_auth_len) { 01472 if (header_auth_len < sizeof(RpcAuthVerifier) || 01473 header_auth_len > RPC_AUTH_VERIFIER_LEN(&(*Header)->common)) { 01474 WARN("bad auth verifier length %d\n", header_auth_len); 01475 status = RPC_S_PROTOCOL_ERROR; 01476 goto fail; 01477 } 01478 01479 /* FIXME: we should accumulate authentication data for the bind, 01480 * bind_ack, alter_context and alter_context_response if necessary. 01481 * however, the details of how this is done is very sketchy in the 01482 * DCE/RPC spec. for all other packet types that have authentication 01483 * verifier data then it is just duplicated in all the fragments */ 01484 memcpy(auth_data, (unsigned char *)payload + data_length, header_auth_len); 01485 01486 /* these packets are handled specially, not by the generic SecurePacket 01487 * function */ 01488 if (!packet_does_auth_negotiation(*Header) && rpcrt4_conn_is_authorized(Connection)) 01489 { 01490 status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_RECEIVE, 01491 CurrentHeader, hdr_length, 01492 (unsigned char *)pMsg->Buffer + buffer_length, data_length, 01493 (RpcAuthVerifier *)auth_data, 01494 auth_data + sizeof(RpcAuthVerifier), 01495 header_auth_len - sizeof(RpcAuthVerifier)); 01496 if (status != RPC_S_OK) goto fail; 01497 } 01498 } 01499 01500 buffer_length += data_length; 01501 if (!(CurrentHeader->common.flags & RPC_FLG_LAST)) { 01502 TRACE("next header\n"); 01503 01504 if (*Header != CurrentHeader) 01505 { 01506 RPCRT4_FreeHeader(CurrentHeader); 01507 CurrentHeader = NULL; 01508 } 01509 HeapFree(GetProcessHeap(), 0, payload); 01510 payload = NULL; 01511 01512 status = RPCRT4_receive_fragment(Connection, &CurrentHeader, &payload); 01513 if (status != RPC_S_OK) goto fail; 01514 01515 first_flag = 0; 01516 } else { 01517 break; 01518 } 01519 } 01520 pMsg->BufferLength = buffer_length; 01521 01522 /* success */ 01523 status = RPC_S_OK; 01524 01525 fail: 01526 RPCRT4_SetThreadCurrentConnection(NULL); 01527 if (CurrentHeader != *Header) 01528 RPCRT4_FreeHeader(CurrentHeader); 01529 if (status != RPC_S_OK) { 01530 I_RpcFree(pMsg->Buffer); 01531 pMsg->Buffer = NULL; 01532 RPCRT4_FreeHeader(*Header); 01533 *Header = NULL; 01534 } 01535 if (auth_data_out && status == RPC_S_OK) { 01536 *auth_length_out = auth_length; 01537 *auth_data_out = auth_data; 01538 } 01539 else 01540 HeapFree(GetProcessHeap(), 0, auth_data); 01541 HeapFree(GetProcessHeap(), 0, payload); 01542 return status; 01543 } 01544 01545 /*********************************************************************** 01546 * RPCRT4_Receive (internal) 01547 * 01548 * Receive a packet from connection and merge the fragments. 01549 */ 01550 static RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, 01551 PRPC_MESSAGE pMsg) 01552 { 01553 return RPCRT4_ReceiveWithAuth(Connection, Header, pMsg, NULL, NULL); 01554 } 01555 01556 /*********************************************************************** 01557 * I_RpcNegotiateTransferSyntax [RPCRT4.@] 01558 * 01559 * Negotiates the transfer syntax used by a client connection by connecting 01560 * to the server. 01561 * 01562 * PARAMS 01563 * pMsg [I] RPC Message structure. 01564 * pAsync [I] Asynchronous state to set. 01565 * 01566 * RETURNS 01567 * Success: RPC_S_OK. 01568 * Failure: Any error code. 01569 */ 01570 RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) 01571 { 01572 RpcBinding* bind = pMsg->Handle; 01573 RpcConnection* conn; 01574 RPC_STATUS status = RPC_S_OK; 01575 01576 TRACE("(%p)\n", pMsg); 01577 01578 if (!bind || bind->server) 01579 { 01580 ERR("no binding\n"); 01581 return RPC_S_INVALID_BINDING; 01582 } 01583 01584 /* if we already have a connection, we don't need to negotiate again */ 01585 if (!pMsg->ReservedForRuntime) 01586 { 01587 RPC_CLIENT_INTERFACE *cif = pMsg->RpcInterfaceInformation; 01588 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; 01589 01590 if (!bind->Endpoint || !bind->Endpoint[0]) 01591 { 01592 TRACE("automatically resolving partially bound binding\n"); 01593 status = RpcEpResolveBinding(bind, cif); 01594 if (status != RPC_S_OK) return status; 01595 } 01596 01597 status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, 01598 &cif->InterfaceId); 01599 01600 if (status == RPC_S_OK) 01601 { 01602 pMsg->ReservedForRuntime = conn; 01603 RPCRT4_AddRefBinding(bind); 01604 } 01605 } 01606 01607 return status; 01608 } 01609 01610 /*********************************************************************** 01611 * I_RpcGetBuffer [RPCRT4.@] 01612 * 01613 * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the 01614 * server interface. 01615 * 01616 * PARAMS 01617 * pMsg [I/O] RPC message information. 01618 * 01619 * RETURNS 01620 * Success: RPC_S_OK. 01621 * Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. 01622 * RPC_S_SERVER_UNAVAILABLE if unable to connect to server. 01623 * ERROR_OUTOFMEMORY if buffer allocation failed. 01624 * 01625 * NOTES 01626 * The pMsg->BufferLength field determines the size of the buffer to allocate, 01627 * in bytes. 01628 * 01629 * Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. 01630 * 01631 * SEE ALSO 01632 * I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). 01633 */ 01634 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) 01635 { 01636 RPC_STATUS status; 01637 RpcBinding* bind = pMsg->Handle; 01638 01639 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); 01640 01641 if (!bind) 01642 { 01643 ERR("no binding\n"); 01644 return RPC_S_INVALID_BINDING; 01645 } 01646 01647 pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength); 01648 TRACE("Buffer=%p\n", pMsg->Buffer); 01649 01650 if (!pMsg->Buffer) 01651 return ERROR_OUTOFMEMORY; 01652 01653 if (!bind->server) 01654 { 01655 status = I_RpcNegotiateTransferSyntax(pMsg); 01656 if (status != RPC_S_OK) 01657 I_RpcFree(pMsg->Buffer); 01658 } 01659 else 01660 status = RPC_S_OK; 01661 01662 return status; 01663 } 01664 01665 /*********************************************************************** 01666 * I_RpcReAllocateBuffer (internal) 01667 */ 01668 static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) 01669 { 01670 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); 01671 pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); 01672 01673 TRACE("Buffer=%p\n", pMsg->Buffer); 01674 return pMsg->Buffer ? RPC_S_OK : ERROR_OUTOFMEMORY; 01675 } 01676 01677 /*********************************************************************** 01678 * I_RpcFreeBuffer [RPCRT4.@] 01679 * 01680 * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from 01681 * the server interface. 01682 * 01683 * PARAMS 01684 * pMsg [I/O] RPC message information. 01685 * 01686 * RETURNS 01687 * RPC_S_OK. 01688 * 01689 * SEE ALSO 01690 * I_RpcGetBuffer(), I_RpcReceive(). 01691 */ 01692 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) 01693 { 01694 RpcBinding* bind = pMsg->Handle; 01695 01696 TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); 01697 01698 if (!bind) 01699 { 01700 ERR("no binding\n"); 01701 return RPC_S_INVALID_BINDING; 01702 } 01703 01704 if (pMsg->ReservedForRuntime) 01705 { 01706 RpcConnection *conn = pMsg->ReservedForRuntime; 01707 RPCRT4_CloseBinding(bind, conn); 01708 RPCRT4_ReleaseBinding(bind); 01709 pMsg->ReservedForRuntime = NULL; 01710 } 01711 I_RpcFree(pMsg->Buffer); 01712 return RPC_S_OK; 01713 } 01714 01715 static void CALLBACK async_apc_notifier_proc(ULONG_PTR ulParam) 01716 { 01717 RPC_ASYNC_STATE *state = (RPC_ASYNC_STATE *)ulParam; 01718 state->u.APC.NotificationRoutine(state, NULL, state->Event); 01719 } 01720 01721 static DWORD WINAPI async_notifier_proc(LPVOID p) 01722 { 01723 RpcConnection *conn = p; 01724 RPC_ASYNC_STATE *state = conn->async_state; 01725 01726 if (state && conn->ops->wait_for_incoming_data(conn) != -1) 01727 { 01728 state->Event = RpcCallComplete; 01729 switch (state->NotificationType) 01730 { 01731 case RpcNotificationTypeEvent: 01732 TRACE("RpcNotificationTypeEvent %p\n", state->u.hEvent); 01733 SetEvent(state->u.hEvent); 01734 break; 01735 case RpcNotificationTypeApc: 01736 TRACE("RpcNotificationTypeApc %p\n", state->u.APC.hThread); 01737 QueueUserAPC(async_apc_notifier_proc, state->u.APC.hThread, (ULONG_PTR)state); 01738 break; 01739 case RpcNotificationTypeIoc: 01740 TRACE("RpcNotificationTypeIoc %p, 0x%x, 0x%lx, %p\n", 01741 state->u.IOC.hIOPort, state->u.IOC.dwNumberOfBytesTransferred, 01742 state->u.IOC.dwCompletionKey, state->u.IOC.lpOverlapped); 01743 PostQueuedCompletionStatus(state->u.IOC.hIOPort, 01744 state->u.IOC.dwNumberOfBytesTransferred, 01745 state->u.IOC.dwCompletionKey, 01746 state->u.IOC.lpOverlapped); 01747 break; 01748 case RpcNotificationTypeHwnd: 01749 TRACE("RpcNotificationTypeHwnd %p 0x%x\n", state->u.HWND.hWnd, 01750 state->u.HWND.Msg); 01751 PostMessageW(state->u.HWND.hWnd, state->u.HWND.Msg, 0, 0); 01752 break; 01753 case RpcNotificationTypeCallback: 01754 TRACE("RpcNotificationTypeCallback %p\n", state->u.NotificationRoutine); 01755 state->u.NotificationRoutine(state, NULL, state->Event); 01756 break; 01757 case RpcNotificationTypeNone: 01758 TRACE("RpcNotificationTypeNone\n"); 01759 break; 01760 default: 01761 FIXME("unknown NotificationType: %d/0x%x\n", state->NotificationType, state->NotificationType); 01762 break; 01763 } 01764 } 01765 01766 return 0; 01767 } 01768 01769 /*********************************************************************** 01770 * I_RpcSend [RPCRT4.@] 01771 * 01772 * Sends a message to the server. 01773 * 01774 * PARAMS 01775 * pMsg [I/O] RPC message information. 01776 * 01777 * RETURNS 01778 * Unknown. 01779 * 01780 * NOTES 01781 * The buffer must have been allocated with I_RpcGetBuffer(). 01782 * 01783 * SEE ALSO 01784 * I_RpcGetBuffer(), I_RpcReceive(), I_RpcSendReceive(). 01785 */ 01786 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) 01787 { 01788 RpcBinding* bind = pMsg->Handle; 01789 RpcConnection* conn; 01790 RPC_STATUS status; 01791 RpcPktHdr *hdr; 01792 01793 TRACE("(%p)\n", pMsg); 01794 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 01795 01796 conn = pMsg->ReservedForRuntime; 01797 01798 hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, 01799 pMsg->BufferLength, 01800 pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT, 01801 &bind->ObjectUuid); 01802 if (!hdr) 01803 return ERROR_OUTOFMEMORY; 01804 hdr->common.call_id = conn->NextCallId++; 01805 01806 status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); 01807 01808 RPCRT4_FreeHeader(hdr); 01809 01810 if (status == RPC_S_OK && pMsg->RpcFlags & RPC_BUFFER_ASYNC) 01811 { 01812 if (!QueueUserWorkItem(async_notifier_proc, conn, WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION)) 01813 status = RPC_S_OUT_OF_RESOURCES; 01814 } 01815 01816 return status; 01817 } 01818 01819 /* is this status something that the server can't recover from? */ 01820 static inline BOOL is_hard_error(RPC_STATUS status) 01821 { 01822 switch (status) 01823 { 01824 case 0: /* user-defined fault */ 01825 case ERROR_ACCESS_DENIED: 01826 case ERROR_INVALID_PARAMETER: 01827 case RPC_S_PROTOCOL_ERROR: 01828 case RPC_S_CALL_FAILED: 01829 case RPC_S_CALL_FAILED_DNE: 01830 case RPC_S_SEC_PKG_ERROR: 01831 return TRUE; 01832 default: 01833 return FALSE; 01834 } 01835 } 01836 01837 /*********************************************************************** 01838 * I_RpcReceive [RPCRT4.@] 01839 */ 01840 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) 01841 { 01842 RpcBinding* bind = pMsg->Handle; 01843 RPC_STATUS status; 01844 RpcPktHdr *hdr = NULL; 01845 RpcConnection *conn; 01846 01847 TRACE("(%p)\n", pMsg); 01848 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 01849 01850 conn = pMsg->ReservedForRuntime; 01851 status = RPCRT4_Receive(conn, &hdr, pMsg); 01852 if (status != RPC_S_OK) { 01853 WARN("receive failed with error %x\n", status); 01854 goto fail; 01855 } 01856 01857 switch (hdr->common.ptype) { 01858 case PKT_RESPONSE: 01859 break; 01860 case PKT_FAULT: 01861 ERR ("we got fault packet with status 0x%x\n", hdr->fault.status); 01862 status = NCA2RPC_STATUS(hdr->fault.status); 01863 if (is_hard_error(status)) 01864 goto fail; 01865 break; 01866 default: 01867 WARN("bad packet type %d\n", hdr->common.ptype); 01868 status = RPC_S_PROTOCOL_ERROR; 01869 goto fail; 01870 } 01871 01872 /* success */ 01873 RPCRT4_FreeHeader(hdr); 01874 return status; 01875 01876 fail: 01877 RPCRT4_FreeHeader(hdr); 01878 RPCRT4_DestroyConnection(conn); 01879 pMsg->ReservedForRuntime = NULL; 01880 return status; 01881 } 01882 01883 /*********************************************************************** 01884 * I_RpcSendReceive [RPCRT4.@] 01885 * 01886 * Sends a message to the server and receives the response. 01887 * 01888 * PARAMS 01889 * pMsg [I/O] RPC message information. 01890 * 01891 * RETURNS 01892 * Success: RPC_S_OK. 01893 * Failure: Any error code. 01894 * 01895 * NOTES 01896 * The buffer must have been allocated with I_RpcGetBuffer(). 01897 * 01898 * SEE ALSO 01899 * I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive(). 01900 */ 01901 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) 01902 { 01903 RPC_STATUS status; 01904 void *original_buffer; 01905 01906 TRACE("(%p)\n", pMsg); 01907 01908 original_buffer = pMsg->Buffer; 01909 status = I_RpcSend(pMsg); 01910 if (status == RPC_S_OK) 01911 status = I_RpcReceive(pMsg); 01912 /* free the buffer replaced by a new buffer in I_RpcReceive */ 01913 if (status == RPC_S_OK) 01914 I_RpcFree(original_buffer); 01915 return status; 01916 } 01917 01918 /*********************************************************************** 01919 * I_RpcAsyncSetHandle [RPCRT4.@] 01920 * 01921 * Sets the asynchronous state of the handle contained in the RPC message 01922 * structure. 01923 * 01924 * PARAMS 01925 * pMsg [I] RPC Message structure. 01926 * pAsync [I] Asynchronous state to set. 01927 * 01928 * RETURNS 01929 * Success: RPC_S_OK. 01930 * Failure: Any error code. 01931 */ 01932 RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync) 01933 { 01934 RpcBinding* bind = pMsg->Handle; 01935 RpcConnection *conn; 01936 01937 TRACE("(%p, %p)\n", pMsg, pAsync); 01938 01939 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 01940 01941 conn = pMsg->ReservedForRuntime; 01942 conn->async_state = pAsync; 01943 01944 return RPC_S_OK; 01945 } 01946 01947 /*********************************************************************** 01948 * I_RpcAsyncAbortCall [RPCRT4.@] 01949 * 01950 * Aborts an asynchronous call. 01951 * 01952 * PARAMS 01953 * pAsync [I] Asynchronous state. 01954 * ExceptionCode [I] Exception code. 01955 * 01956 * RETURNS 01957 * Success: RPC_S_OK. 01958 * Failure: Any error code. 01959 */ 01960 RPC_STATUS WINAPI I_RpcAsyncAbortCall(PRPC_ASYNC_STATE pAsync, ULONG ExceptionCode) 01961 { 01962 FIXME("(%p, %d): stub\n", pAsync, ExceptionCode); 01963 return RPC_S_INVALID_ASYNC_HANDLE; 01964 } Generated on Sun May 27 2012 04:26:05 for ReactOS by
1.7.6.1
|