Handle more RPC service names
[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     call = MSRPC_NewCall();
983
984     if (len > MAX_RPC_MSG_SIZE)
985         return CM_ERROR_BUFFERTOOSMALL;
986
987     MSRPC_AllocBuffer(&call->in, len);
988     memcpy(call->in.buf_data, buffer, len);
989     call->in.buf_pos = len;
990     call->in.buf_length = call->in.buf_pos;
991     call->status = MSRPC_CALL_MSGRECEIVED;
992
993     if (userp) {
994         call->cm_userp = userp;
995         cm_HoldUser(userp);
996     }
997
998     MSRPC_PutCall(conn, call);
999
1000     return 0;
1001 }
1002
1003 /*! \brief Prepare to read the next message from the RPC output queue
1004
1005    Each RPC message received is queued until the response is required.
1006    MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
1007    and prepare the output buffer to be sent to the caller.
1008  */
1009 int
1010 MSRPC_PrepareRead(msrpc_conn * conn)
1011 {
1012     msrpc_call * call;
1013     int code = 0;
1014
1015     while (conn->head) {
1016         call = conn->head;
1017
1018         if (call->status == MSRPC_CALL_SKIP ||
1019             call->status == MSRPC_CALL_MSGSENT ||
1020             (call->status == MSRPC_CALL_DISPATCHED &&
1021              call->out.buf_length == 0)) {
1022
1023             MSRPC_DequeueCall(conn, call);
1024             MSRPC_FreeCall(call);
1025             continue;
1026         }
1027
1028         if (call->status == MSRPC_CALL_MSGRECEIVED) {
1029             code = dispatch_call(conn);
1030
1031             /* If the dispatch failed, then we discard the message.
1032                If the error was handled and a response packet was
1033                created, dispatch_call() would return 0. */
1034
1035             if (code) {
1036                 MSRPC_DequeueCall(conn, call);
1037                 MSRPC_FreeCall(call);
1038             }
1039             continue;
1040         }
1041
1042         break;                  /* the status wasn't SKIP or
1043                                    MSGRECEIVED, or we successfully
1044                                    dispatched the message. */
1045     }
1046
1047     if (conn->head == NULL)
1048         return CM_ERROR_BADFD;
1049
1050     if (conn->head->status == MSRPC_CALL_DISPATCHED ||
1051         conn->head->status == MSRPC_CALL_MSGSENDING)
1052         return 0;
1053     else
1054         return CM_ERROR_BADFD;
1055 }
1056
1057 /*! \brief Return the size of the buffer for the next RPC message
1058
1059    Given the maximum size of the buffer, returns the actual size of
1060    the data that will be copied.  If the return value is 0, there is
1061    no data to be sent to the caller either because there was no RPC
1062    message queued or the queued message could not be dispatched.
1063  */
1064 int
1065 MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
1066 {
1067     int code;
1068     msrpc_call *call;
1069
1070     max_len = min(max_len, conn->max_recv_frag);
1071
1072     code = MSRPC_PrepareRead(conn);
1073     if (code)
1074         return 0;
1075
1076     call = conn->head;
1077
1078     if (call &&
1079         (call->status == MSRPC_CALL_DISPATCHED ||
1080          call->status == MSRPC_CALL_MSGSENDING)) {
1081
1082         switch(call->out.pdu_type) {
1083         case PDU_TYPE_RESPONSE:
1084             {
1085                 /* This calculation should mirror what
1086                    MSRPC_ReadMessage() does below. */
1087
1088                 int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1089                 unsigned int len;
1090
1091                 len = min(max_len, conn->max_recv_frag);
1092
1093                 if (call->out.buf_pos % fragment_size == 0) {
1094                     if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
1095                         return 0;
1096
1097                     len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
1098                 } else {
1099                     unsigned int to_copy;
1100
1101                     to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
1102                                   call->out.buf_length - call->out.buf_pos);
1103                     len = min(to_copy, len);
1104                 }
1105
1106                 return len;
1107             }
1108
1109         case PDU_TYPE_BIND_ACK:
1110         case PDU_TYPE_FAULT:
1111         case PDU_TYPE_BIND_NAK:
1112             {
1113                 int len = min(call->out.buf_length - call->out.buf_pos, max_len);
1114
1115                 return len;
1116             }
1117         }
1118
1119         return 0;
1120     } else {
1121         return 0;
1122     }
1123 }
1124
1125 /*! \brief Read the next message from the RPC queue
1126
1127    Copies the next chunk of data from the response buffer to the
1128    buffer indicated by \a buffer and \a len.
1129
1130    \retval 0 The data was copied to the buffer.  There is either no
1131        more data to send or the existence of more data is implicit in
1132        the data already sent. I.e. fragment flags were set
1133        appropriately to indicate more data and we are at a fragment
1134        boundary.
1135
1136    \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
1137        there is more data to be sent.
1138
1139    \retval Else something went wrong.  The data was not copied to the
1140        buffer successfully.
1141  */
1142 int
1143 MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
1144 {
1145     int code;
1146     msrpc_call * call;
1147
1148     code = MSRPC_PrepareRead(conn);
1149     if (code)
1150         return code;
1151
1152     if (conn->head &&
1153         (conn->head->status == MSRPC_CALL_DISPATCHED ||
1154          conn->head->status == MSRPC_CALL_MSGSENDING)) {
1155
1156         call = conn->head;
1157
1158         switch(call->out.pdu_type) {
1159         case PDU_TYPE_RESPONSE:
1160             {
1161                 BYTE * o_buffer = call->out.buf_data;
1162                 unsigned int o_alloc = call->out.buf_alloc;
1163                 unsigned int o_pos = call->out.buf_pos;
1164                 unsigned int o_len = call->out.buf_length;
1165                 unsigned int start_pos = o_pos;
1166                 unsigned int fragment_size;
1167                 fcursor o;
1168
1169                 /* If call->out.buf_pos falls on a fragment boundary:
1170
1171                      Assume that we are starting a new fragment and deal accordingly.
1172
1173                    Else
1174
1175                      Assume we are continuing a fragment.
1176                  */
1177
1178                 fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1179
1180                 /* Don't send more than the max_recv_frag */
1181                 len = min(len, conn->max_recv_frag);
1182
1183                 /* Switch the supplied user buffer with the output
1184                    buffer */
1185                 call->out.buf_data = buffer;
1186                 call->out.buf_length = 0;
1187                 call->out.buf_alloc = len;
1188                 call->out.buf_pos = 0;
1189
1190                 if (o_pos % fragment_size == 0) {
1191
1192                     /* New fragment:
1193
1194                        We need to write the packet headers and
1195                        fragment bits here.  The length of the buffer
1196                        should be at least big enough to hold the
1197                        entire envelope.  We don't handle the case were
1198                        the envelope itself is too big.
1199
1200                      */
1201
1202                     if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
1203                         return CM_ERROR_INVAL;
1204                     }
1205
1206                     code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
1207                     if (code)
1208                         return code;
1209
1210                     write_u_int32(&o, o_len); /* allocation hint */
1211                     write_u_int16(&o, call->context_id); /* presentation context ID */
1212                     write_u_int8(&o, 0);                 /* cancel count */
1213                     write_u_int8(&o, 0);                 /* reserved */
1214
1215                     {
1216                         int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
1217                         int rc;
1218
1219                         O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1220
1221                         /* the fragment size of the message is the minimum of:
1222
1223                            - max_recv_frag for the connection
1224                            - envelope size + (full message size - start offset)
1225
1226                          */
1227                         rc = closeMessage(&o, call,
1228                                           min(conn->max_recv_frag,
1229                                               RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
1230                         if (rc)
1231                             return rc;
1232
1233                         o_pos += to_copy;
1234
1235                         /* If there is more data to be sent and we are
1236                            not at a fragment boundary after the last
1237                            send, we return CM_ERROR_RPC_MOREDATA.
1238                            Having more fragments to send is not a case
1239                            we indicate via a return value. */
1240
1241                         if (o_pos < o_len &&
1242                             o_pos < start_pos + fragment_size)
1243                             code = CM_ERROR_RPC_MOREDATA;
1244                     }
1245
1246                     if (start_pos + fragment_size < o_len)
1247                         buffer[3] &= ~PFC_LAST_FRAG;
1248
1249                     if (start_pos != 0)
1250                         buffer[3] &= ~PFC_FIRST_FRAG;
1251
1252                 } else {
1253
1254                     /* Continuation:
1255
1256                        The packet header should have already been sent
1257                        in a previous block.
1258
1259                      */
1260                     unsigned int to_copy;
1261
1262                     INITC(&o, call->out.buf_data, call->out.buf_alloc);
1263
1264                     to_copy = min(fragment_size - (o_pos % fragment_size),
1265                                   o_len - o_pos);
1266                     to_copy = min(to_copy, SPC_LEFT(&o));
1267
1268                     O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1269
1270                     o_pos += to_copy;
1271
1272                     if (o_pos < o_len && (o_pos % fragment_size) != 0)
1273                         code = CM_ERROR_RPC_MOREDATA;
1274                 }
1275
1276                 call->out.buf_data = o_buffer;
1277                 call->out.buf_alloc = o_alloc;
1278                 call->out.buf_pos = o_pos;
1279                 call->out.buf_length = o_len;
1280
1281                 if (call->out.buf_pos < call->out.buf_length) {
1282                     call->status = MSRPC_CALL_MSGSENDING;
1283                 } else {
1284                     call->status = MSRPC_CALL_MSGSENT;
1285                     MSRPC_DequeueCall(conn, call);
1286                     MSRPC_FreeCall(call);
1287                 }
1288             }
1289             return code;
1290
1291         case PDU_TYPE_BIND_ACK:
1292         case PDU_TYPE_FAULT:
1293         case PDU_TYPE_BIND_NAK:
1294             {
1295                 unsigned int to_send;
1296
1297                 /* These types of packets are already fully formed.
1298                    We don't need to wrap them in an envelope.  They
1299                    also don't fragment. */
1300
1301                 to_send = call->out.buf_length - call->out.buf_pos;
1302
1303                 if (len < to_send)
1304                     code = CM_ERROR_RPC_MOREDATA;
1305                 else
1306                     len = to_send;
1307
1308                 if (len > 0) {
1309                     memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
1310                 }
1311
1312                 call->out.buf_pos += len;
1313
1314                 if (call->out.buf_pos < call->out.buf_length) {
1315                     call->status = MSRPC_CALL_MSGSENDING;
1316                 } else {
1317                     call->status = MSRPC_CALL_MSGSENT;
1318                     MSRPC_DequeueCall(conn, call);
1319                     MSRPC_FreeCall(call);
1320                 }
1321             }
1322             return code;
1323         }
1324
1325         return CM_ERROR_INVAL;
1326     } else {
1327         return 0;
1328     }
1329 }
1330
1331 pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
1332
1333 DWORD msrpc_tls_user_slot = 0;
1334
1335 static void
1336 msrpc_user_slot_init_func(void)
1337 {
1338     msrpc_tls_user_slot = TlsAlloc();
1339 }
1340
1341 cm_user_t *
1342 MSRPC_GetCmUser(void)
1343 {
1344     pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1345
1346     return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
1347 }
1348
1349 static void
1350 MSRPC_SetCmUser(cm_user_t * userp)
1351 {
1352     pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1353
1354     TlsSetValue(msrpc_tls_user_slot, userp);
1355 }
1356
1357 typedef struct I_RpcAllocatedBuffer {
1358     DWORD magic;                /* == _RPCALLOCATEDBUFFER_MAGIC */
1359 #define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
1360     struct I_RpcAllocatedBuffer * next;
1361
1362     /* Data goes here */
1363 } I_RpcAllocatedBuffer;
1364
1365 #define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
1366
1367 RPC_STATUS
1368 RPC_ENTRY
1369 I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1370 {
1371     I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
1372     I_RpcAllocatedBuffer * oldBuffer = NULL;
1373
1374     if (Message->Buffer) {
1375         oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1376     }
1377
1378     if (newBuffer) {
1379         newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
1380         newBuffer->next = oldBuffer;
1381
1382         Message->Buffer = &newBuffer[1];
1383     } else {
1384         return ERROR_OUTOFMEMORY;
1385     }
1386
1387     return RPC_S_OK;
1388 }
1389
1390 RPC_STATUS
1391 RPC_ENTRY
1392 I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1393 {
1394     if (Message->Buffer) {
1395         I_RpcAllocatedBuffer * buffer;
1396
1397         buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1398
1399         while (buffer) {
1400             I_RpcAllocatedBuffer * bnext;
1401
1402             bnext = buffer->next;
1403
1404             I_RpcFree(buffer);
1405
1406             buffer = bnext;
1407         }
1408
1409         Message->Buffer = NULL;
1410     }
1411
1412     return RPC_S_OK;
1413 }
1414
1415 unsigned char  *
1416 RPC_ENTRY
1417 NdrServerInitializeNew(
1418     PRPC_MESSAGE            pRpcMsg,
1419     PMIDL_STUB_MESSAGE      pStubMsg,
1420     PMIDL_STUB_DESC         pStubDesc
1421     )
1422 {
1423     ZeroMemory(pStubMsg, sizeof(*pStubMsg));
1424
1425     pStubMsg->RpcMsg = pRpcMsg;
1426     pStubMsg->Buffer = pRpcMsg->Buffer;
1427     pStubMsg->BufferStart = pRpcMsg->Buffer;
1428     pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
1429     pStubMsg->BufferLength = pRpcMsg->BufferLength;
1430     pStubMsg->MemorySize = pRpcMsg->BufferLength;
1431     pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
1432     pStubMsg->pfnFree = pStubDesc->pfnFree;
1433     pStubMsg->StubDesc = pStubDesc;
1434     pStubMsg->dwDestContext = MSHCTX_LOCAL;
1435
1436     return NULL;
1437 }
1438
1439 void
1440 MSRPC_Init(void) {
1441     RPC_SRVSVC_Init();
1442 }
1443
1444 void
1445 MSRPC_Shutdown(void) {
1446     RPC_SRVSVC_Shutdown();
1447 }
1448
1449 int
1450 MSRPC_IsWellKnownService(const clientchar_t * lastNamep)
1451 {
1452     return
1453         cm_ClientStrCmpIA(lastNamep,  _C("\\srvsvc")) == 0 ||
1454         cm_ClientStrCmpIA(lastNamep,  _C("\\wkssvc")) == 0 ||
1455         cm_ClientStrCmpIA(lastNamep,  _C("\\spoolss")) == 0 ||
1456         cm_ClientStrCmpIA(lastNamep,  _C("\\winreg")) == 0 ||
1457         cm_ClientStrCmpIA(lastNamep,  _C("\\lsass")) == 0 ||
1458         cm_ClientStrCmpIA(lastNamep,  _C("\\lsarpc")) == 0 ||
1459         cm_ClientStrCmpIA(lastNamep,  _C("\\samr")) == 0 ||
1460         cm_ClientStrCmpIA(lastNamep,  _C("\\netlogon")) == 0 ||
1461         cm_ClientStrCmpIA(lastNamep,  _C("\\ntsvcs")) == 0 ||
1462         cm_ClientStrCmpIA(lastNamep,  _C("\\eventlog")) == 0 ||
1463         cm_ClientStrCmpIA(lastNamep,  _C("\\svcctl")) == 0 ||
1464         cm_ClientStrCmpIA(lastNamep,  _C("\\browse")) == 0 ||
1465         cm_ClientStrCmpIA(lastNamep,  _C("\\msgsvc")) == 0 ||
1466         cm_ClientStrCmpIA(lastNamep,  _C("\\w32time")) == 0 ||
1467         cm_ClientStrCmpIA(lastNamep,  _C("ipc$")) == 0;
1468 }