Windows: engage path mtu discovery for rx
[openafs.git] / src / WINNT / afsd / msrpc.c
1 /*
2  * Copyright (c) 2009 Secure Endpoints Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #include <malloc.h>
26 #include "ms-wkssvc.h"
27 #include "ms-srvsvc.h"
28 #include "afsd.h"
29 #include "cm_btree.h"
30 #include "cm_nls.h"
31 #include "msrpc.h"
32
33 static void
34 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size);
35
36 static void
37 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size);
38
39 static void
40 MSRPC_FreeBuffer(msrpc_buffer * buf);
41
42 static void
43 MSRPC_SetCmUser(cm_user_t * userp);
44
45 /*! \brief Interface list
46
47    This is the list of interfaces that are exported through this RPC
48    module.  The *_ifspec variable is defined the <interface>_s.c file
49    that is generated by MIDL.  We have to use an extra level of
50    indirection because the actual RPC_SERVER_INTERFACE structure is
51    not exported in the generated code.
52  */
53 RPC_SERVER_INTERFACE **_Interfaces[] = {
54     (RPC_SERVER_INTERFACE **) &wkssvc_v1_0_s_ifspec,
55     (RPC_SERVER_INTERFACE **) &srvsvc_v3_0_s_ifspec,
56 };
57
58 const int n_Interfaces = sizeof(_Interfaces)/sizeof(_Interfaces[0]);
59
60 /* Serialization  */
61
62 #define RPC_ALIGNMENT 8
63 #define ALIGNTO8(x) (((((x) - 1)/8) + 1) * 8)
64
65 typedef struct fcursor {
66     BYTE * pos;
67     BYTE * end;
68 } fcursor;
69
70 #define INITC(pfc, buf, len) (pfc)->pos = (BYTE *)(buf); (pfc)->end = (pfc)->pos + (len)
71
72 #define SPC_LEFT(pfc) ((unsigned int)((pfc)->end - (pfc)->pos))
73 #define IS_SPC(pfc, n) (SPC_LEFT(pfc) >= (n))
74
75 __inline BYTE READB(fcursor * pfc) {
76     BYTE b = *pfc->pos;
77     pfc->pos++;
78     return b;
79 }
80
81 #define READW(pfc) (((WORD)READB(pfc)) | (((WORD)READB(pfc)) << 8))
82 #define READDW(pfc) (((DWORD)READW(pfc)) | (((DWORD)READW(pfc)) << 16))
83 #define O_READS(pfc, s) do { memcpy(s, (pfc)->pos, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
84 #define O_READA(pfc, a) do { memcpy(&a, (pfc)->pos, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
85 #define O_READSZ(pfc, s, sz) do { memcpy(s, (pfc)->pos, sz); (pfc)->pos += sz; } while (0)
86 #define O_RALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) READB(pfc); } while (0)
87 #define O_RALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) READB(pfc); } while (0)
88
89 __inline void WRITEB(fcursor * pfc, BYTE b) {
90     *pfc->pos = b;
91     pfc->pos++;
92 }
93
94 #define WRITEW(pfc, w) (WRITEB(pfc, ((w) & 0xff)), WRITEB(pfc, (((w) >> 8) & 0xff)))
95 #define WRITEDW(pfc, dw) (WRITEW(pfc, ((dw) & 0xffff)), WRITEW(pfc, (((dw) >> 16) & 0xffff)))
96 #define O_WRITES(pfc, s) do { memcpy((pfc)->pos, s, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
97 #define O_WRITEA(pfc, a) do { memcpy((pfc)->pos, &a, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
98 #define O_WRITESZ(pfc, s, sz) do { memcpy((pfc)->pos, s, sz); (pfc)->pos += sz; } while (0)
99 #define O_WALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) WRITEB(pfc, 0); } while (0)
100 #define O_WALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) WRITEB(pfc, 0); } while (0)
101
102 #define iread_u_int8(pfc)  READB(pfc)
103 #define iread_byte(pfc) READB(pfc)
104 #define iread_u_int16(pfc) READW(pfc)
105 #define iread_u_int32(pfc) READDW(pfc)
106
107 #define write_u_int8(pfc, i) WRITEB(pfc, i)
108 #define write_byte(pfc, i) WRITEB(pfc, i)
109 #define write_u_int16(pfc, i) WRITEW(pfc, i)
110 #define write_u_int32(pfc, i) WRITEDW(pfc, i)
111
112 /*! \brief Supported RPC protocol version numbers */
113 RPC_VERSION msrpc_supported_protocol_versions[] = {
114     { 5, 0 },                   /* 5.0 */
115     { 5, 1 }                    /* 5.1 */
116 };
117
118 const int n_msrpc_supported_protocol_versions = sizeof(msrpc_supported_protocol_versions)/sizeof(msrpc_supported_protocol_versions[0]);
119
120 #define IS_PROTOCOL_VER_SUPPORTED(_maj, _min) ((_maj) == 5 && ((_min) == 0 || (_min) == 1))
121
122 /*! \brief Number of bytes of envelope overhead for an RPC response PDU */
123 #define RPC_RESPONSE_ENVELOPE_OVERHEAD 24
124
125 static int
126 read_E_CommonHeader(fcursor *pc, E_CommonHeader * pr)
127 {
128     if (IS_SPC(pc, 16)) {
129
130         pr->rpc_vers       = iread_u_int8(pc);
131         pr->rpc_vers_minor = iread_u_int8(pc);
132         pr->PTYPE          = iread_u_int8(pc);
133         pr->pfc_flags      = iread_u_int8(pc);
134         O_READA(pc, pr->packed_drep);
135         pr->frag_length    = iread_u_int16(pc);
136         pr->auth_length    = iread_u_int16(pc);
137         pr->call_id        = iread_u_int32(pc);
138
139         return 0;
140
141     } else {
142         return CM_ERROR_BADFORMAT;
143     }
144 }
145
146 static int
147 write_E_CommonHeader(fcursor * pc, msrpc_conn * conn,
148                      msrpc_call * call, PDU_TYPE pdu_type)
149 {
150     INITC(pc, call->out.buf_data, call->out.buf_alloc);
151
152     call->out.pdu_type = pdu_type;
153
154     if (IS_SPC(pc, 16)) {
155         write_u_int8(pc, conn->rpc_vers);       /* protocol version */
156         write_u_int8(pc, conn->rpc_vers_minor); /* minor version */
157         write_u_int8(pc, pdu_type);
158         write_u_int8(pc, PFC_FIRST_FRAG|PFC_LAST_FRAG);
159
160         write_byte(pc, 0x10);   /* Data representation */
161         write_byte(pc, 0);
162         write_byte(pc, 0);
163         write_byte(pc, 0);
164
165         write_u_int16(pc, 0);   /* Fragment ength, to be filled in
166                                    later */
167         write_u_int16(pc, 0);   /* Length of auth data. Always 0 since
168                                    we don't do authentication for RPC
169                                    calls.*/
170         write_u_int32(pc, call->call_id);
171
172         return 0;
173     } else {
174         return CM_ERROR_BUFFERTOOSMALL;
175     }
176 }
177
178 #define USE_CURRENT_BUFFER_LENGTH (-1)
179 static int
180 closeMessage(fcursor * pc, msrpc_call * call, ptrdiff_t len)
181 {
182
183     unsigned short slen;
184
185     if (len == USE_CURRENT_BUFFER_LENGTH)
186         len = pc->pos - call->out.buf_data;
187
188     if (len >= USHRT_MAX)
189         return CM_ERROR_TOOBIG;
190     slen = (unsigned short)len;
191
192     pc->pos = &call->out.buf_data[8];
193     write_u_int16(pc, slen);
194     call->out.buf_length = slen;
195
196     return 0;
197 }
198
199 static int
200 read_UUID(fcursor * pc,
201           UUID * uuid)
202 {
203     if (IS_SPC(pc, sizeof(*uuid))) {
204         O_READS(pc, uuid);
205         return 0;
206     } else {
207         return CM_ERROR_BADFORMAT;
208     }
209 }
210
211 static int
212 write_UUID(fcursor * pc,
213            const UUID * uuid)
214 {
215     if (IS_SPC(pc, sizeof(*uuid))) {
216         O_WRITES(pc, uuid);
217         return 0;
218     } else {
219         return CM_ERROR_BUFFERTOOSMALL;
220     }
221 }
222
223 static int
224 read_RPC_VERSION(fcursor * pc,
225                  RPC_VERSION * ver)
226 {
227     if (IS_SPC(pc, 4)) {
228         ver->MajorVersion = iread_u_int16(pc);
229         ver->MinorVersion = iread_u_int16(pc);
230         return 0;
231     } else {
232         return CM_ERROR_BADFORMAT;
233     }
234 }
235
236 static int
237 write_RPC_VERSION(fcursor * pc,
238                   const RPC_VERSION * ver)
239 {
240     if (IS_SPC(pc, 4)) {
241         write_u_int16(pc, ver->MajorVersion);
242         write_u_int16(pc, ver->MinorVersion);
243         return 0;
244     } else {
245         return CM_ERROR_BUFFERTOOSMALL;
246     }
247 }
248
249 static int
250 read_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
251                            RPC_SYNTAX_IDENTIFIER * psi)
252 {
253     int code;
254
255     code = read_UUID(pc, &psi->SyntaxGUID);
256     if (code)
257         return code;
258     code = read_RPC_VERSION(pc, &psi->SyntaxVersion);
259     return code;
260 }
261
262 static int
263 write_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
264                             const RPC_SYNTAX_IDENTIFIER * psi)
265 {
266     int code;
267
268     code = write_UUID(pc, &psi->SyntaxGUID);
269     if (code)
270         return code;
271     code = write_RPC_VERSION(pc, &psi->SyntaxVersion);
272     return code;
273 }
274
275 static int
276 is_equal_RPC_SYNTAX_IDENTIFIER(const RPC_SYNTAX_IDENTIFIER * s1,
277                                const RPC_SYNTAX_IDENTIFIER * s2)
278 {
279     return
280         IsEqualGUID(&s1->SyntaxGUID, &s2->SyntaxGUID) &&
281         s1->SyntaxVersion.MajorVersion == s2->SyntaxVersion.MajorVersion &&
282         s2->SyntaxVersion.MinorVersion == s2->SyntaxVersion.MinorVersion;
283 }
284
285 #define FAULT_PDU_PACKET_SIZE 32
286
287 /*! \brief Write a fault PDU as the output of this call */
288 static int
289 write_fault_PDU(msrpc_conn * conn, msrpc_call * call,
290                 u_int32 status, u_int8 flags)
291 {
292     fcursor o;
293
294     MSRPC_AllocBuffer(&call->out, FAULT_PDU_PACKET_SIZE);
295
296     write_E_CommonHeader(&o, conn, call, PDU_TYPE_FAULT);
297
298     write_u_int32(&o, 16);      /* allocation hint */
299     write_u_int16(&o, call->context_id); /* presentation context ID */
300
301     write_u_int8(&o, 0);        /* cancel count */
302     write_u_int8(&o, 0);        /* reserved */
303
304     write_u_int32(&o, status);  /* status code */
305
306     O_WALIGN8(&o);              /* alignment */
307
308     closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
309
310     if (flags) {
311         call->out.buf_data[3] |= flags;
312     }
313
314     call->status = MSRPC_CALL_DISPATCHED;
315
316     return 0;
317 }
318
319 #define BIND_NAK_PDU_PACKET_SIZE 18
320
321 /*! \brief Write a bind_nak PDU as the output of this call */
322 static int
323 write_bind_nak_PDU(msrpc_conn * conn, msrpc_call * call,
324                    BIND_REJECT_REASON reject_reason)
325 {
326     fcursor o;
327     unsigned buf_size = BIND_NAK_PDU_PACKET_SIZE;
328
329     if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED)
330         buf_size += n_msrpc_supported_protocol_versions * 2 + 1;
331
332     MSRPC_AllocBuffer(&call->out, buf_size);
333
334     write_E_CommonHeader(&o, conn, call, PDU_TYPE_BIND_NAK);
335
336     write_u_int16(&o, reject_reason);
337
338     if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED) {
339         int i;
340
341         write_u_int8(&o, n_msrpc_supported_protocol_versions);
342
343         for (i=0; i < n_msrpc_supported_protocol_versions; i++) {
344             write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MajorVersion);
345             write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MinorVersion);
346         }
347     }
348
349     closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
350
351     call->status = MSRPC_CALL_DISPATCHED;
352
353     return 0;
354 }
355
356 static int
357 handle_ConnBind(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
358 {
359     int code = 0;
360
361     if (!IS_SPC(in, 12))
362         return CM_ERROR_BADFORMAT;
363
364     conn->max_xmit_frag = iread_u_int16(in);
365     conn->max_recv_frag = iread_u_int16(in);
366     conn->assoc_group_id = iread_u_int32(in);
367
368     conn->rpc_vers = call->in_header->rpc_vers;
369     conn->rpc_vers_minor = call->in_header->rpc_vers_minor;
370
371     if (conn->assoc_group_id == 0)
372         conn->assoc_group_id = 1;
373
374     write_E_CommonHeader(out, conn, call, PDU_TYPE_BIND_ACK);
375
376     write_u_int16(out, conn->max_xmit_frag);
377     write_u_int16(out, conn->max_recv_frag);
378     write_u_int32(out, conn->assoc_group_id);
379
380     if (conn->secondary_address) {
381         int len = (int)strlen(conn->secondary_address) + 1;
382
383         write_u_int16(out, len);
384         O_WRITESZ(out, conn->secondary_address, len);
385     } else {
386         write_u_int16(out, 0);
387     }
388
389     O_WALIGN4(out);
390
391     /* presentation context negotiation */
392     {
393         int n_context_elem;
394         int i;
395
396         n_context_elem = iread_u_int8(in);
397         iread_u_int8(in);       /* skip over reserved */
398         iread_u_int16(in);      /* skip over reserved */
399
400         write_u_int8(out, n_context_elem);
401         write_u_int8(out, 0);   /* pad */
402         write_u_int16(out, 0);  /* pad */
403
404         for (i=0; i < n_context_elem; i++) {
405             int n_transfer_syn;
406             RPC_SYNTAX_IDENTIFIER abstract_syntax;
407             RPC_SYNTAX_IDENTIFIER transfer_syntax;
408             RPC_SERVER_INTERFACE *interf = NULL;
409             int j, k;
410
411             if (!IS_SPC(in, 4 + 16))
412                 return CM_ERROR_BADFORMAT;
413
414             call->context_id = iread_u_int16(in);
415             n_transfer_syn = iread_u_int8(in);
416             iread_u_int8(in);   /* skip */
417
418             code = read_RPC_SYNTAX_IDENTIFIER(in, &abstract_syntax);
419             if (code)
420                 return code;
421
422             for (j=0; j < n_Interfaces; j++) {
423                 interf = *_Interfaces[j];
424
425                 if (is_equal_RPC_SYNTAX_IDENTIFIER(&abstract_syntax, &interf->InterfaceId))
426                     break;
427             }
428
429             if (j < n_Interfaces) {
430                 for (k=0; k < n_transfer_syn; k++) {
431                     code = read_RPC_SYNTAX_IDENTIFIER(in, &transfer_syntax);
432                     if (code)
433                         return code;
434
435                     if (is_equal_RPC_SYNTAX_IDENTIFIER(&transfer_syntax, &interf->TransferSyntax))
436                         break;
437                 }
438             }
439
440             if (j < n_Interfaces && k < n_transfer_syn) {
441                 /* accepted */
442                 write_u_int16(out, 0);
443                 write_u_int16(out, 0);
444                 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
445
446                 conn->interface = interf;
447             } else {
448                 int reason;
449
450                 if (j >= n_Interfaces)
451                     reason = 1; /* abstract syntax not supported */
452                 else
453                     reason = 2;        /* transfer syntax not supported */
454                 write_u_int16(out, 2); /* provider rejection */
455                 write_u_int16(out, reason);
456                 ZeroMemory(&transfer_syntax, sizeof(transfer_syntax));
457                 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
458             }
459         }
460     }
461
462     return closeMessage(out, call, USE_CURRENT_BUFFER_LENGTH);
463 }
464
465 static int
466 handle_ConnRequest(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
467 {
468     int code = 0;
469
470     int alloc_hint;
471     unsigned int op_num;
472     RPC_STATUS _Status = RPC_S_OK;
473
474     int len;
475
476     if (!IS_SPC(in, 8))
477         return CM_ERROR_BADFORMAT;
478
479     alloc_hint = iread_u_int32(in);
480     call->context_id = iread_u_int16(in);
481     op_num = iread_u_int16(in);
482
483     if (call->in_header->pfc_flags & PFC_OBJECT_UUID) {
484         UUID uuid;
485
486         code = read_UUID(in, &uuid);
487         if (code)
488             return code;
489     }
490
491     O_RALIGN8(in);
492
493     if (conn->interface == NULL) {
494         /* if there was no interface selected, we can't go ahead with
495            this request. */
496         return write_fault_PDU(conn, call, RPC_S_NO_BINDINGS, PFC_DID_NOT_EXECUTE);
497     }
498
499     len = SPC_LEFT(in);
500
501     if (op_num < 0 || op_num >= conn->interface->DispatchTable->DispatchTableCount ||
502         conn->interface->DispatchTable->DispatchTable[op_num] == NULL) {
503
504         return write_fault_PDU(conn, call, RPC_S_PROCNUM_OUT_OF_RANGE, PFC_DID_NOT_EXECUTE);
505     }
506
507     call->msg.BufferLength = len;
508     call->msg.ProcNum = op_num;
509     call->msg.TransferSyntax = &conn->interface->TransferSyntax;
510     call->msg.RpcInterfaceInformation = conn->interface;
511
512     _Status = I_RpcGetBuffer(&call->msg);
513     if ( _Status || call->msg.Buffer == NULL) {
514         return write_fault_PDU(conn, call, RPC_S_SERVER_OUT_OF_MEMORY, PFC_DID_NOT_EXECUTE);
515     }
516
517     memcpy(call->msg.Buffer, in->pos, len);
518
519     MSRPC_SetCmUser(call->cm_userp);
520
521     RpcTryExcept
522         {
523             (*conn->interface->DispatchTable->DispatchTable[op_num])(&call->msg);
524         }
525     RpcExcept ( 1 )
526         {
527             code = CM_ERROR_UNKNOWN;
528         }
529     RpcEndExcept;
530
531     MSRPC_SetCmUser(NULL);
532
533     if (code == 0) {
534         call->out.pdu_type = PDU_TYPE_RESPONSE;
535
536         MSRPC_AllocBuffer(&call->out, call->msg.BufferLength);
537         call->out.buf_length = call->msg.BufferLength;
538         memcpy(call->out.buf_data, call->msg.Buffer, call->out.buf_length);
539     } else {
540         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, 0);
541     }
542
543     return code;
544 }
545
546 static int
547 merge_fragment_Bind(msrpc_call * call, E_CommonHeader * ph,
548                         msrpc_call * ncall, E_CommonHeader *pnh)
549 {
550     if (ph->auth_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
551         ph->frag_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
552         pnh->auth_length + 16 > pnh->frag_length)
553         return CM_ERROR_TOOBIG;
554
555     MSRPC_ReallocBuffer(&call->in, call->in.buf_length + pnh->auth_length);
556     if (call->in.buf_data == NULL)
557         return CM_ERROR_TOOBIG;
558
559     memcpy(call->in.buf_data + ph->frag_length,
560            ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
561            pnh->auth_length);
562
563     call->in.buf_length += pnh->auth_length;
564     ph->frag_length += pnh->auth_length;
565     ph->auth_length += pnh->auth_length;
566
567     if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
568         ph->pfc_flags |= PFC_LAST_FRAG;
569     }
570
571     return 0;
572 }
573
574 static int
575 merge_fragment_Request(msrpc_call * call, E_CommonHeader * ph,
576                            msrpc_call * ncall, E_CommonHeader * pnh)
577 {
578     int new_auth_length = pnh->auth_length;
579     int new_stub_length = (int)pnh->frag_length - (pnh->auth_length + 24);
580
581     if (pnh->pfc_flags & PFC_OBJECT_UUID)
582         new_stub_length -= 16;
583
584     if (ph->auth_length + new_auth_length > _UI16_MAX ||
585         ph->frag_length + new_stub_length + new_auth_length > _UI16_MAX ||
586         pnh->auth_length + 24 > pnh->frag_length)
587         return CM_ERROR_TOOBIG;
588
589     MSRPC_ReallocBuffer(&call->in, call->in.buf_length + new_auth_length + new_stub_length);
590     if (call->in.buf_data == NULL)
591         return CM_ERROR_TOOBIG;
592
593     if(ph->auth_length)
594         memmove(call->in.buf_data + (ph->frag_length - ph->auth_length),
595                 call->in.buf_data + (ph->frag_length - ph->auth_length) + new_stub_length,
596                 ph->auth_length);
597
598     memcpy(call->in.buf_data + (ph->frag_length - ph->auth_length),
599            ncall->in.buf_data + (pnh->frag_length - (new_auth_length + new_stub_length)),
600            new_stub_length);
601
602     memcpy(call->in.buf_data + ph->frag_length + new_stub_length,
603            ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
604            pnh->auth_length);
605
606     call->in.buf_length += new_auth_length + new_stub_length;
607     ph->frag_length += new_auth_length + new_stub_length;
608     ph->auth_length += new_auth_length;
609
610     if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
611         ph->pfc_flags |= PFC_LAST_FRAG;
612     }
613
614     return 0;
615 }
616
617 static int
618 assemble_message(msrpc_conn * conn)
619 {
620     int code = 0;
621     msrpc_call * call;
622     msrpc_call * ncall;
623     E_CommonHeader h;
624     fcursor c;
625
626     call = conn->head;
627
628     if (call == NULL)
629         return CM_ERROR_INVAL;
630
631     INITC(&c, call->in.buf_data, call->in.buf_length);
632
633     code = read_E_CommonHeader(&c, &h);
634     if (code)
635         return code;
636
637     if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) ==
638         (PFC_FIRST_FRAG | PFC_LAST_FRAG))
639         return 0;
640
641     if ((h.pfc_flags & PFC_FIRST_FRAG) != PFC_FIRST_FRAG)
642         return CM_ERROR_INVAL;
643
644     for (ncall = call->next; ncall; ncall = ncall->next) {
645         fcursor nc;
646         E_CommonHeader nh;
647
648         INITC(&nc, ncall->in.buf_data, ncall->in.buf_length);
649
650         code = read_E_CommonHeader(&nc, &nh);
651
652         if (nh.call_id != h.call_id)
653             continue;
654
655         if ((nh.pfc_flags & PFC_FIRST_FRAG) != 0)
656             continue;
657
658         switch(h.PTYPE) {
659         case PDU_TYPE_BIND:
660         case PDU_TYPE_ALTER_CONTEXT:
661             code = merge_fragment_Bind(call, &h, ncall, &nh);
662             break;
663
664         case PDU_TYPE_REQUEST:
665             code = merge_fragment_Request(call, &h, ncall, &nh);
666             break;
667
668         default:
669             code = CM_ERROR_INVAL;
670         }
671
672         ncall->status = MSRPC_CALL_SKIP;
673
674         if (nh.pfc_flags & PFC_LAST_FRAG) {
675             break;
676         }
677     }
678
679     c.pos = &call->in.buf_data[3];
680     write_u_int8(&c, h.pfc_flags);
681     write_u_int16(&c, h.frag_length);
682     write_u_int16(&c, h.auth_length);
683
684     return code;
685 }
686
687 static int
688 dispatch_call(msrpc_conn * conn)
689 {
690     int code = 0;
691     fcursor c;
692     fcursor o;
693     E_CommonHeader h;
694     msrpc_call * call;
695
696     call = conn->head;
697
698     if (call == NULL ||
699         call->status != MSRPC_CALL_MSGRECEIVED)
700         return CM_ERROR_INVAL;
701
702     MSRPC_AllocBuffer(&call->out, DEF_RPC_MSG_SIZE);
703
704  retry_buffer:
705
706     INITC(&c, call->in.buf_data, call->in.buf_length);
707
708     code = read_E_CommonHeader(&c, &h);
709     if (code)
710         return code;
711
712     if (!IS_PROTOCOL_VER_SUPPORTED(h.rpc_vers, h.rpc_vers_minor)) {
713         if (h.PTYPE == PDU_TYPE_BIND) {
714             return write_bind_nak_PDU(conn, call, BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED);
715         } else {
716             /* we shouldn't get here, but just in case */
717             return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
718         }
719     }
720
721     if (h.packed_drep[0] != 0x10 ||
722         h.packed_drep[1] != 0 ||
723         h.packed_drep[2] != 0 ||
724         h.packed_drep[3] != 0) {
725
726         if (h.PTYPE == PDU_TYPE_BIND) {
727             return write_bind_nak_PDU(conn, call, BIND_REJ_REASON_NOT_SPECIFIED);
728         } else {
729             return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
730         }
731     }
732
733     if (h.frag_length > call->in.buf_length) {
734         return CM_ERROR_INVAL;
735     }
736
737     if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) !=
738         (PFC_FIRST_FRAG | PFC_LAST_FRAG)) {
739         code = assemble_message(conn);
740         if (code == 0)
741             goto retry_buffer;
742         else
743             return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
744     }
745
746     if (h.auth_length != 0) {
747         return write_fault_PDU(conn, call, RPC_S_BINDING_HAS_NO_AUTH, PFC_DID_NOT_EXECUTE);
748     }
749
750     call->call_id = h.call_id;
751
752     call->in.pdu_type = h.PTYPE;
753
754     INITC(&o, call->out.buf_data, call->out.buf_alloc);
755
756     call->in_header = &h;
757
758     code = CM_ERROR_INVAL;
759
760     switch (h.PTYPE) {
761     case PDU_TYPE_REQUEST:
762         code = handle_ConnRequest(conn, call, &c, &o);
763         break;
764
765     case PDU_TYPE_BIND:
766         code = handle_ConnBind(conn, call, &c, &o);
767         break;
768
769     case PDU_TYPE_ALTER_CONTEXT:
770         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
771         break;
772
773     case PDU_TYPE_SHUTDOWN:
774         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
775         break;
776
777     case PDU_TYPE_CO_CANCEL:
778         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
779         break;
780
781     case PDU_TYPE_ORPHANED:
782         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
783         break;
784
785     default:
786         code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
787     }
788
789     call->in_header = NULL;
790
791     call->status = MSRPC_CALL_DISPATCHED;
792
793     return code;
794 }
795
796 static void
797 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size)
798 {
799     if (buf->buf_alloc < size) {
800         if (buf->buf_data)
801             _aligned_free(buf->buf_data);
802
803         buf->buf_alloc = ALIGNTO8(size);
804         buf->buf_data = _aligned_malloc(buf->buf_alloc, RPC_ALIGNMENT);
805         buf->buf_length = 0;
806         buf->buf_pos = 0;
807     }
808 }
809
810 static void
811 MSRPC_FreeBuffer(msrpc_buffer * buf)
812 {
813     if (buf->buf_data) {
814         _aligned_free(buf->buf_data);
815         buf->buf_data = NULL;
816         buf->buf_alloc = 0;
817         buf->buf_length = 0;
818         buf->buf_pos = 0;
819     }
820 }
821
822 static void
823 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size)
824 {
825     if (buf->buf_alloc < size) {
826         BYTE * new_buf;
827
828         buf->buf_alloc = ALIGNTO8(size);
829         new_buf = _aligned_realloc(buf->buf_data, buf->buf_alloc, RPC_ALIGNMENT);
830         if (new_buf != NULL) {
831             buf->buf_data = new_buf;
832         } else {
833             MSRPC_FreeBuffer(buf);
834         }
835     }
836 }
837
838 static msrpc_call *
839 MSRPC_NewCall(void)
840 {
841     msrpc_call * c;
842
843     c = calloc(sizeof(*c), 1);
844
845     c->msg.Handle = NULL;
846     c->msg.DataRepresentation = 0x00000010;
847     c->msg.Buffer = NULL;
848     c->msg.BufferLength = 0;
849     c->msg.TransferSyntax = NULL;
850
851     return c;
852 }
853
854 static int
855 MSRPC_PutCall(msrpc_conn * conn, msrpc_call * pcall)
856 {
857     if (conn->tail) {
858         conn->tail->next = pcall;
859         pcall->prev = conn->tail;
860         conn->tail = pcall;
861         pcall->next = NULL;
862     } else {
863         conn->head = conn->tail = pcall;
864         pcall->next = pcall->prev = NULL;
865     }
866     return 0;
867 }
868
869 static int
870 MSRPC_DequeueCall(msrpc_conn * conn, msrpc_call * call)
871 {
872     if (call->prev)
873         call->prev->next = call->next;
874     if (call->next)
875         call->next->prev = call->prev;
876
877     if (conn->head  && conn->head == call)
878         conn->head = call->next;
879
880     if (conn->tail && conn->tail == call)
881         conn->tail = call->prev;
882
883     call->next = call->prev = NULL;
884
885     return 0;
886 }
887
888 static int
889 MSRPC_GetCall(msrpc_conn * conn, msrpc_call ** ppcall)
890 {
891     if (conn->head) {
892         *ppcall = conn->head;
893         conn->head = conn->head->next;
894         if (conn->head)
895             conn->head->prev = NULL;
896         (*ppcall)->next = (*ppcall)->prev = NULL;
897         if (conn->tail == *ppcall)
898             conn->tail = NULL;
899         return 0;
900     } else {
901         *ppcall = NULL;
902         return 1;
903     }
904 }
905
906 static int
907 MSRPC_FreeCall(msrpc_call * call)
908 {
909     I_RpcFreeBuffer(&call->msg);
910     MSRPC_FreeBuffer(&call->in);
911     MSRPC_FreeBuffer(&call->out);
912
913     if (call->cm_userp) {
914         cm_ReleaseUser(call->cm_userp);
915         call->cm_userp = NULL;
916     }
917
918     ZeroMemory(call, sizeof(*call));
919     free (call);
920     return 0;
921 }
922
923 /*! \brief Initialize a msrpc_conn
924
925    \param [out] conn Connection to initialize
926
927    \param [in] secondary_address An optional secondary address for the
928        query.  Typically for RPCs to wellknown endpoints such as
929        SRVSVC or WKSSVC, this is a named pipe address (e.g.:
930        \PIPE\srvsvc ).
931
932    \return Always returns 0.
933  */
934 int
935 MSRPC_InitConn(msrpc_conn * conn, const char * secondary_address)
936 {
937     ZeroMemory(conn, sizeof(*conn));
938     if (secondary_address) {
939         conn->secondary_address = strdup(secondary_address);
940     }
941     return 0;
942 }
943
944 /*! \brief Free a msrcp_conn structure contents
945
946    This doesn't free the msrpc_conn object, but frees the contents.
947  */
948 int
949 MSRPC_FreeConn(msrpc_conn * conn)
950 {
951     msrpc_call * call = NULL;
952
953     while(!MSRPC_GetCall(conn, &call)) {
954         MSRPC_FreeCall(call);
955     }
956
957     if (conn->secondary_address)
958         free(conn->secondary_address);
959
960     ZeroMemory(conn, sizeof(*conn));
961
962     return 0;
963 }
964
965 /*! \brief Write an RPC message into the RPC module
966
967    This function should be used by message mode RPC transports to
968    submit a single message.  if successful, the message will be queued
969    for dispatch.  The RPC will not be executed until
970    MSRPC_PrepareRead() or MSRPC_ReadMessageLength() or
971    MSRPC_ReadMessage() is called.
972  */
973 int
974 MSRPC_WriteMessage(msrpc_conn * conn, BYTE * buffer, unsigned int len,
975                    cm_user_t * userp)
976 {
977     msrpc_call * call;
978
979     if (len == 0)
980         return CM_ERROR_INVAL;
981
982     if (len > MAX_RPC_MSG_SIZE)
983         return CM_ERROR_BUFFERTOOSMALL;
984
985     call = MSRPC_NewCall();
986     if (!call)
987         return ENOMEM;
988
989     MSRPC_AllocBuffer(&call->in, len);
990     memcpy(call->in.buf_data, buffer, len);
991     call->in.buf_pos = len;
992     call->in.buf_length = call->in.buf_pos;
993     call->status = MSRPC_CALL_MSGRECEIVED;
994
995     if (userp) {
996         call->cm_userp = userp;
997         cm_HoldUser(userp);
998     }
999
1000     MSRPC_PutCall(conn, call);
1001
1002     return 0;
1003 }
1004
1005 /*! \brief Prepare to read the next message from the RPC output queue
1006
1007    Each RPC message received is queued until the response is required.
1008    MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
1009    and prepare the output buffer to be sent to the caller.
1010  */
1011 int
1012 MSRPC_PrepareRead(msrpc_conn * conn)
1013 {
1014     msrpc_call * call;
1015     int code = 0;
1016
1017     while (conn->head) {
1018         call = conn->head;
1019
1020         if (call->status == MSRPC_CALL_SKIP ||
1021             call->status == MSRPC_CALL_MSGSENT ||
1022             (call->status == MSRPC_CALL_DISPATCHED &&
1023              call->out.buf_length == 0)) {
1024
1025             MSRPC_DequeueCall(conn, call);
1026             MSRPC_FreeCall(call);
1027             continue;
1028         }
1029
1030         if (call->status == MSRPC_CALL_MSGRECEIVED) {
1031             code = dispatch_call(conn);
1032
1033             /* If the dispatch failed, then we discard the message.
1034                If the error was handled and a response packet was
1035                created, dispatch_call() would return 0. */
1036
1037             if (code) {
1038                 MSRPC_DequeueCall(conn, call);
1039                 MSRPC_FreeCall(call);
1040             }
1041             continue;
1042         }
1043
1044         break;                  /* the status wasn't SKIP or
1045                                    MSGRECEIVED, or we successfully
1046                                    dispatched the message. */
1047     }
1048
1049     if (conn->head == NULL)
1050         return CM_ERROR_BADFD;
1051
1052     if (conn->head->status == MSRPC_CALL_DISPATCHED ||
1053         conn->head->status == MSRPC_CALL_MSGSENDING)
1054         return 0;
1055     else
1056         return CM_ERROR_BADFD;
1057 }
1058
1059 /*! \brief Return the size of the buffer for the next RPC message
1060
1061    Given the maximum size of the buffer, returns the actual size of
1062    the data that will be copied.  If the return value is 0, there is
1063    no data to be sent to the caller either because there was no RPC
1064    message queued or the queued message could not be dispatched.
1065  */
1066 int
1067 MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
1068 {
1069     int code;
1070     msrpc_call *call;
1071
1072     max_len = min(max_len, conn->max_recv_frag);
1073
1074     code = MSRPC_PrepareRead(conn);
1075     if (code)
1076         return 0;
1077
1078     call = conn->head;
1079
1080     if (call &&
1081         (call->status == MSRPC_CALL_DISPATCHED ||
1082          call->status == MSRPC_CALL_MSGSENDING)) {
1083
1084         switch(call->out.pdu_type) {
1085         case PDU_TYPE_RESPONSE:
1086             {
1087                 /* This calculation should mirror what
1088                    MSRPC_ReadMessage() does below. */
1089
1090                 int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1091                 unsigned int len;
1092
1093                 len = min(max_len, conn->max_recv_frag);
1094
1095                 if (call->out.buf_pos % fragment_size == 0) {
1096                     if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
1097                         return 0;
1098
1099                     len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
1100                 } else {
1101                     unsigned int to_copy;
1102
1103                     to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
1104                                   call->out.buf_length - call->out.buf_pos);
1105                     len = min(to_copy, len);
1106                 }
1107
1108                 return len;
1109             }
1110
1111         case PDU_TYPE_BIND_ACK:
1112         case PDU_TYPE_FAULT:
1113         case PDU_TYPE_BIND_NAK:
1114             {
1115                 int len = min(call->out.buf_length - call->out.buf_pos, max_len);
1116
1117                 return len;
1118             }
1119         }
1120
1121         return 0;
1122     } else {
1123         return 0;
1124     }
1125 }
1126
1127 /*! \brief Read the next message from the RPC queue
1128
1129    Copies the next chunk of data from the response buffer to the
1130    buffer indicated by \a buffer and \a len.
1131
1132    \retval 0 The data was copied to the buffer.  There is either no
1133        more data to send or the existence of more data is implicit in
1134        the data already sent. I.e. fragment flags were set
1135        appropriately to indicate more data and we are at a fragment
1136        boundary.
1137
1138    \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
1139        there is more data to be sent.
1140
1141    \retval Else something went wrong.  The data was not copied to the
1142        buffer successfully.
1143  */
1144 int
1145 MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
1146 {
1147     int code;
1148     msrpc_call * call;
1149
1150     code = MSRPC_PrepareRead(conn);
1151     if (code)
1152         return code;
1153
1154     if (conn->head &&
1155         (conn->head->status == MSRPC_CALL_DISPATCHED ||
1156          conn->head->status == MSRPC_CALL_MSGSENDING)) {
1157
1158         call = conn->head;
1159
1160         switch(call->out.pdu_type) {
1161         case PDU_TYPE_RESPONSE:
1162             {
1163                 BYTE * o_buffer = call->out.buf_data;
1164                 unsigned int o_alloc = call->out.buf_alloc;
1165                 unsigned int o_pos = call->out.buf_pos;
1166                 unsigned int o_len = call->out.buf_length;
1167                 unsigned int start_pos = o_pos;
1168                 unsigned int fragment_size;
1169                 fcursor o;
1170
1171                 /* If call->out.buf_pos falls on a fragment boundary:
1172
1173                      Assume that we are starting a new fragment and deal accordingly.
1174
1175                    Else
1176
1177                      Assume we are continuing a fragment.
1178                  */
1179
1180                 fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1181
1182                 /* Don't send more than the max_recv_frag */
1183                 len = min(len, conn->max_recv_frag);
1184
1185                 /* Switch the supplied user buffer with the output
1186                    buffer */
1187                 call->out.buf_data = buffer;
1188                 call->out.buf_length = 0;
1189                 call->out.buf_alloc = len;
1190                 call->out.buf_pos = 0;
1191
1192                 if (o_pos % fragment_size == 0) {
1193
1194                     /* New fragment:
1195
1196                        We need to write the packet headers and
1197                        fragment bits here.  The length of the buffer
1198                        should be at least big enough to hold the
1199                        entire envelope.  We don't handle the case were
1200                        the envelope itself is too big.
1201
1202                      */
1203
1204                     if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
1205                         return CM_ERROR_INVAL;
1206                     }
1207
1208                     code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
1209                     if (code)
1210                         return code;
1211
1212                     write_u_int32(&o, o_len); /* allocation hint */
1213                     write_u_int16(&o, call->context_id); /* presentation context ID */
1214                     write_u_int8(&o, 0);                 /* cancel count */
1215                     write_u_int8(&o, 0);                 /* reserved */
1216
1217                     {
1218                         int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
1219                         int rc;
1220
1221                         O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1222
1223                         /* the fragment size of the message is the minimum of:
1224
1225                            - max_recv_frag for the connection
1226                            - envelope size + (full message size - start offset)
1227
1228                          */
1229                         rc = closeMessage(&o, call,
1230                                           min(conn->max_recv_frag,
1231                                               RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
1232                         if (rc)
1233                             return rc;
1234
1235                         o_pos += to_copy;
1236
1237                         /* If there is more data to be sent and we are
1238                            not at a fragment boundary after the last
1239                            send, we return CM_ERROR_RPC_MOREDATA.
1240                            Having more fragments to send is not a case
1241                            we indicate via a return value. */
1242
1243                         if (o_pos < o_len &&
1244                             o_pos < start_pos + fragment_size)
1245                             code = CM_ERROR_RPC_MOREDATA;
1246                     }
1247
1248                     if (start_pos + fragment_size < o_len)
1249                         buffer[3] &= ~PFC_LAST_FRAG;
1250
1251                     if (start_pos != 0)
1252                         buffer[3] &= ~PFC_FIRST_FRAG;
1253
1254                 } else {
1255
1256                     /* Continuation:
1257
1258                        The packet header should have already been sent
1259                        in a previous block.
1260
1261                      */
1262                     unsigned int to_copy;
1263
1264                     INITC(&o, call->out.buf_data, call->out.buf_alloc);
1265
1266                     to_copy = min(fragment_size - (o_pos % fragment_size),
1267                                   o_len - o_pos);
1268                     to_copy = min(to_copy, SPC_LEFT(&o));
1269
1270                     O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1271
1272                     o_pos += to_copy;
1273
1274                     if (o_pos < o_len && (o_pos % fragment_size) != 0)
1275                         code = CM_ERROR_RPC_MOREDATA;
1276                 }
1277
1278                 call->out.buf_data = o_buffer;
1279                 call->out.buf_alloc = o_alloc;
1280                 call->out.buf_pos = o_pos;
1281                 call->out.buf_length = o_len;
1282
1283                 if (call->out.buf_pos < call->out.buf_length) {
1284                     call->status = MSRPC_CALL_MSGSENDING;
1285                 } else {
1286                     call->status = MSRPC_CALL_MSGSENT;
1287                     MSRPC_DequeueCall(conn, call);
1288                     MSRPC_FreeCall(call);
1289                 }
1290             }
1291             return code;
1292
1293         case PDU_TYPE_BIND_ACK:
1294         case PDU_TYPE_FAULT:
1295         case PDU_TYPE_BIND_NAK:
1296             {
1297                 unsigned int to_send;
1298
1299                 /* These types of packets are already fully formed.
1300                    We don't need to wrap them in an envelope.  They
1301                    also don't fragment. */
1302
1303                 to_send = call->out.buf_length - call->out.buf_pos;
1304
1305                 if (len < to_send)
1306                     code = CM_ERROR_RPC_MOREDATA;
1307                 else
1308                     len = to_send;
1309
1310                 if (len > 0) {
1311                     memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
1312                 }
1313
1314                 call->out.buf_pos += len;
1315
1316                 if (call->out.buf_pos < call->out.buf_length) {
1317                     call->status = MSRPC_CALL_MSGSENDING;
1318                 } else {
1319                     call->status = MSRPC_CALL_MSGSENT;
1320                     MSRPC_DequeueCall(conn, call);
1321                     MSRPC_FreeCall(call);
1322                 }
1323             }
1324             return code;
1325         }
1326
1327         return CM_ERROR_INVAL;
1328     } else {
1329         return 0;
1330     }
1331 }
1332
1333 pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
1334
1335 DWORD msrpc_tls_user_slot = 0;
1336
1337 static void
1338 msrpc_user_slot_init_func(void)
1339 {
1340     msrpc_tls_user_slot = TlsAlloc();
1341 }
1342
1343 cm_user_t *
1344 MSRPC_GetCmUser(void)
1345 {
1346     pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1347
1348     return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
1349 }
1350
1351 static void
1352 MSRPC_SetCmUser(cm_user_t * userp)
1353 {
1354     pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1355
1356     TlsSetValue(msrpc_tls_user_slot, userp);
1357 }
1358
1359 typedef struct I_RpcAllocatedBuffer {
1360     DWORD magic;                /* == _RPCALLOCATEDBUFFER_MAGIC */
1361 #define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
1362     struct I_RpcAllocatedBuffer * next;
1363
1364     /* Data goes here */
1365 } I_RpcAllocatedBuffer;
1366
1367 #define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
1368
1369 RPC_STATUS
1370 RPC_ENTRY
1371 I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1372 {
1373     I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
1374     I_RpcAllocatedBuffer * oldBuffer = NULL;
1375
1376     if (Message->Buffer) {
1377         oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1378     }
1379
1380     if (newBuffer) {
1381         newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
1382         newBuffer->next = oldBuffer;
1383
1384         Message->Buffer = &newBuffer[1];
1385     } else {
1386         return ERROR_OUTOFMEMORY;
1387     }
1388
1389     return RPC_S_OK;
1390 }
1391
1392 RPC_STATUS
1393 RPC_ENTRY
1394 I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1395 {
1396     if (Message->Buffer) {
1397         I_RpcAllocatedBuffer * buffer;
1398
1399         buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1400
1401         while (buffer) {
1402             I_RpcAllocatedBuffer * bnext;
1403
1404             bnext = buffer->next;
1405
1406             I_RpcFree(buffer);
1407
1408             buffer = bnext;
1409         }
1410
1411         Message->Buffer = NULL;
1412     }
1413
1414     return RPC_S_OK;
1415 }
1416
1417 unsigned char  *
1418 RPC_ENTRY
1419 NdrServerInitializeNew(
1420     PRPC_MESSAGE            pRpcMsg,
1421     PMIDL_STUB_MESSAGE      pStubMsg,
1422     PMIDL_STUB_DESC         pStubDesc
1423     )
1424 {
1425     ZeroMemory(pStubMsg, sizeof(*pStubMsg));
1426
1427     pStubMsg->RpcMsg = pRpcMsg;
1428     pStubMsg->Buffer = pRpcMsg->Buffer;
1429     pStubMsg->BufferStart = pRpcMsg->Buffer;
1430     pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
1431     pStubMsg->BufferLength = pRpcMsg->BufferLength;
1432     pStubMsg->MemorySize = pRpcMsg->BufferLength;
1433     pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
1434     pStubMsg->pfnFree = pStubDesc->pfnFree;
1435     pStubMsg->StubDesc = pStubDesc;
1436     pStubMsg->dwDestContext = MSHCTX_LOCAL;
1437
1438     return NULL;
1439 }
1440
1441 void
1442 MSRPC_Init(void) {
1443     RPC_SRVSVC_Init();
1444 }
1445
1446 void
1447 MSRPC_Shutdown(void) {
1448     RPC_SRVSVC_Shutdown();
1449 }
1450
1451 int
1452 MSRPC_IsWellKnownService(const clientchar_t * lastNamep)
1453 {
1454     return
1455         cm_ClientStrCmpIA(lastNamep,  _C("\\srvsvc")) == 0 ||
1456         cm_ClientStrCmpIA(lastNamep,  _C("\\wkssvc")) == 0 ||
1457         cm_ClientStrCmpIA(lastNamep,  _C("\\spoolss")) == 0 ||
1458         cm_ClientStrCmpIA(lastNamep,  _C("\\winreg")) == 0 ||
1459         cm_ClientStrCmpIA(lastNamep,  _C("\\lsass")) == 0 ||
1460         cm_ClientStrCmpIA(lastNamep,  _C("\\lsarpc")) == 0 ||
1461         cm_ClientStrCmpIA(lastNamep,  _C("\\samr")) == 0 ||
1462         cm_ClientStrCmpIA(lastNamep,  _C("\\netlogon")) == 0 ||
1463         cm_ClientStrCmpIA(lastNamep,  _C("\\ntsvcs")) == 0 ||
1464         cm_ClientStrCmpIA(lastNamep,  _C("\\eventlog")) == 0 ||
1465         cm_ClientStrCmpIA(lastNamep,  _C("\\svcctl")) == 0 ||
1466         cm_ClientStrCmpIA(lastNamep,  _C("\\browse")) == 0 ||
1467         cm_ClientStrCmpIA(lastNamep,  _C("\\msgsvc")) == 0 ||
1468         cm_ClientStrCmpIA(lastNamep,  _C("\\w32time")) == 0 ||
1469         cm_ClientStrCmpIA(lastNamep,  _C("ipc$")) == 0;
1470 }