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