afsifs-20050615
[openafs.git] / src / WINNT / afsrdr / ifs_rpc.c
1 /* copyright (c) 2005
2  * the regents of the university of michigan
3  * all rights reserved
4  * 
5  * permission is granted to use, copy, create derivative works and
6  * redistribute this software and such derivative works for any purpose,
7  * so long as the name of the university of michigan is not used in
8  * any advertising or publicity pertaining to the use or distribution
9  * of this software without specific, written prior authorization.  if
10  * the above copyright notice or any other identification of the
11  * university of michigan is included in any copy of any portion of
12  * this software, then the disclaimer below must also be included.
13  * 
14  * this software is provided as is, without representation from the
15  * university of michigan as to its fitness for any purpose, and without
16  * warranty by the university of michigan of any kind, either express 
17  * or implied, including without limitation the implied warranties of
18  * merchantability and fitness for a particular purpose.  the regents
19  * of the university of michigan shall not be liable for any damages,   
20  * including special, indirect, incidental, or consequential damages, 
21  * with respect to any claim arising out or in connection with the use
22  * of the software, even if it has been or is hereafter advised of the
23  * possibility of such damages.
24  */
25
26 /* versioning history
27  * 
28  * 03-jun 2005 (eric williams) entered into versioning
29  */
30
31 #ifdef RPC_KERN
32 #include <ntifs.h>
33 #include "ifs_rpc.h"
34 #include "afsrdr.h"
35 #else
36 #include "ifs_rpc.h"
37 #endif
38 #include "kif.h"
39
40 /* general internal functions */
41 rpc_t *rpc_create(int size_hint);
42 void rpc_destroy(rpc_t *rpc);
43 int rpc_marshal_long(rpc_t *rpc, ULONG data);
44 int rpc_marshal_longlong(rpc_t *rpc, LARGE_INTEGER data);
45 int rpc_marshal_wstr(rpc_t *rpc, WCHAR *str);
46 int rpc_unmarshal_long(rpc_t *rpc, ULONG *data);
47 int rpc_unmarshal_longlong(rpc_t *rpc, LARGE_INTEGER *data);
48 int rpc_unmarshal_wstr(rpc_t *rpc, WCHAR *str);
49
50 /* kernel-queue specific internal functions */
51 #ifdef RPC_KERN
52 int rpc_queue(rpc_t *rpc);
53 rpc_queue_bulk(rpc_t *rpc, char *out_bulk, ULONG out_len, char *in_bulk, ULONG in_len);
54 rpc_cancel(rpc_t *rpc);
55 rpc_send_reg(rpc_t *rpc, char *out_buf);
56 rpc_queue_bulk_mdl(rpc_t *rpc, MDL *mdl);
57 rpc_t *rpc_find(int id);
58 rpc_t *rpc_upgrade(rpc_t *rpc, int old_status, int new_status);
59 rpc_wait(rpc_t *rpc, BOOLEAN long_op);
60 rpc_send_mdl(rpc_t *rpc, char *out_buf);
61 #endif
62
63 /* internal timing functions (not used) */
64 #ifdef RPC_KERN
65 #define TIMING_START()          LARGE_INTEGER start, stop; \
66                                                         start.QuadPart = KeQueryInterruptTime();
67 #define TIMING_END(name)        stop.QuadPart = KeQueryInterruptTime(); \
68                                                         rpt5((name, "%s %d", name, (ULONG)(stop.QuadPart - start.QuadPart)));
69 #endif
70
71
72 /* rpc security kernel functions */
73 #ifdef RPC_KERN
74 struct rpc_cred_map_entry
75         {
76         void *token;
77         PETHREAD thread;
78         };
79
80 struct rpc_cred_map_entry cred_map[20];
81 rpc_t *rpc_list_head = NULL;
82
83 rpc_set_context(void *context)
84         {
85         int x, empty, ret;
86         PETHREAD thd;
87
88         thd = PsGetCurrentThread();
89         empty = -1;
90         ret = 0;
91
92         // LOCKLOCK
93         for (x = 0; x < 20; x++)
94                 {
95                 if (cred_map[x].thread == NULL)
96                         empty = x;
97                 if (cred_map[x].thread == thd)
98                         {
99                         cred_map[x].token = context;
100                         goto done;
101                         }
102                 }
103         if (empty != -1)
104                 {
105                 cred_map[empty].thread = thd;
106                 cred_map[empty].token = context;
107                 }
108         else
109                 ret = -1;
110
111         done:
112                 // UNLOCKUNLOCK
113                 return ret;
114         }
115
116 void *rpc_get_context()
117         {
118         int x;
119         PETHREAD thd;
120
121         thd = PsGetCurrentThread();
122
123         // no lock
124         for (x = 0; x < 20; x++)
125                 if (cred_map[x].thread == thd)
126                         return cred_map[x].token;
127         // no unlock
128         return NULL;
129         }
130
131 rpc_remove_context()
132         {
133         int x;
134         PETHREAD thd;
135
136         thd = PsGetCurrentThread();
137         // no lock
138         for (x = 0; x < 20; x++)
139                 if (cred_map[x].thread == thd)
140                         {
141                         cred_map[x].token = NULL;
142                         cred_map[x].thread = NULL;
143                         return 0;
144                         }
145
146         // no unlock
147         return -1;
148         }
149 #endif
150
151
152 /* rpc internal functions for kernel */
153 #ifdef RPC_KERN
154 rpc_t *rpc_create(int size_hint)
155         {
156         ULONG size;
157         rpc_t *rpc;
158         SECURITY_SUBJECT_CONTEXT subj_context;
159         PACCESS_TOKEN acc_token;
160         LUID auth_id;
161         LARGE_INTEGER user_id;
162         NTSTATUS status;
163         HANDLE token;
164
165         token = rpc_get_context();
166         ASSERT(token);
167         status = SeQueryAuthenticationIdToken(token, &auth_id);
168
169         user_id.LowPart = auth_id.LowPart;
170         user_id.HighPart = auth_id.HighPart;
171
172         ifs_lock_rpcs();
173
174         if (!(rpc = rpc_upgrade(NULL, 0, 1)))
175                 {
176                 size = sizeof(rpc_t) + 4096*10;
177                 rpc = ExAllocatePoolWithTag(NonPagedPool, size, 0x1234);
178                 if (!rpc)
179                         _asm int 3;
180                 memset(rpc, 0, size);
181                 rpc->next = rpc_list_head;
182                 rpc_list_head = rpc;
183                 rpc_upgrade(rpc, 0, 1);
184                 }
185
186         rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
187         rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+2048*10;
188
189         rpc->key = rand() + 10;
190         rpc_marshal_long(rpc, rpc->key);
191         rpc->bulk_out_len = (ULONG*)rpc->out_pos;
192         rpc_marshal_long(rpc, 0);
193
194         /*SeCaptureSubjectContext(&subj_context);
195         acc_token = SeQuerySubjectContextToken(&subj_context);
196         status = SeQueryAuthenticationIdToken(acc_token, &auth_id);*/
197         /**token = rpc_get_context();
198         ASSERT(token);
199         status = SeQueryAuthenticationIdToken(token, &auth_id);
200
201         user_id.LowPart = auth_id.LowPart;
202         user_id.HighPart = auth_id.HighPart;
203         SeReleaseSubjectContext(&subj_context);*/
204
205         rpc_marshal_longlong(rpc, user_id);
206
207         ifs_unlock_rpcs();
208
209         return rpc;
210         }
211
212 void rpc_destroy(rpc_t *rpc)
213         {
214         rpc_t *curr;
215         int count;
216
217         /*ExFreePoolWithTag(rpc, 0x1234);*/
218         ifs_lock_rpcs();
219
220         if (rpc_upgrade(rpc, -1, 0))
221                 ;
222
223         ifs_unlock_rpcs();
224         }
225 #endif
226
227
228 /* rpc internal functions for usermode */
229 #ifndef RPC_KERN
230 rpc_t *rpc_create(int size_hint)
231         {
232         ULONG size;
233         rpc_t *rpc;
234         ULONG status;
235
236         size = sizeof(rpc_t) + 4096;
237         rpc = malloc(size);
238         if (!rpc)
239                 _asm int 3;
240         memset(rpc, 0, size);
241
242         rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
243         rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+2048;
244
245         rpc->key = rand() + 10;
246         rpc_marshal_long(rpc, rpc->key);
247
248         return rpc;
249         }
250
251 void rpc_destroy(rpc_t *rpc)
252         {
253         if (!rpc)
254                 return;
255                 //_asm int 3;
256
257         free(rpc);
258         }
259
260 rpc_transact(rpc_t *rpc)
261         {
262         HANDLE hf;
263         int ret;
264         ULONG header_len;
265         DWORD err, read = 0;
266
267         if (!rpc)
268                 return IFSL_GENERIC_FAILURE;
269
270         header_len = rpc->out_pos - rpc->out_buf;
271
272         read = 2048;
273         return ifs_TransactRpc(rpc->out_buf, header_len, rpc->in_buf, &read);
274         }
275 #endif
276
277
278 /* upcall stubs */
279 #ifdef RPC_KERN
280 uc_namei(WCHAR *name, ULONG *fid)
281         {
282         rpc_t *rpc;
283         ULONG status;
284         MDL *mdl;
285         TIMING_START();
286         /* put namei cache here */
287
288         rpc = rpc_create(0);
289
290         rpc_marshal_long(rpc, RPC_NAMEI);
291         rpc_marshal_long(rpc, wcslen(name));
292
293         rpc_queue_bulk(rpc, (void*)name, (wcslen(name)+1)*sizeof(wchar_t), NULL, 0);
294
295         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
296                 {
297                 rpc_cancel(rpc);
298                 rpt0(("cancel", "cancel namei"));
299                 return IFSL_RPC_TIMEOUT;
300                 }
301
302         rpc_unmarshal_long(rpc, &status);
303         rpc_unmarshal_long(rpc, fid);
304
305         rpc_destroy(rpc);
306         TIMING_END("namei");
307         return status;
308         }
309
310 uc_check_access(ULONG fid, ULONG access, ULONG *granted)
311         {
312         rpc_t *rpc;
313         ULONG status;
314         TIMING_START();
315
316         rpc = rpc_create(0);
317
318         rpc_marshal_long(rpc, RPC_CHECK_ACCESS);
319         rpc_marshal_long(rpc, fid);
320         rpc_marshal_long(rpc, access);
321
322         rpc_queue(rpc);
323         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
324                 {
325                 rpc_cancel(rpc);
326                 rpt0(("cancel", "cancel access"));
327                 return IFSL_RPC_TIMEOUT;
328                 }
329
330         rpc_unmarshal_long(rpc, &status);
331         rpc_unmarshal_long(rpc, granted);
332
333         rpc_destroy(rpc);
334         TIMING_END("access");
335         return status;
336         }
337
338 uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *granted, ULONG *fid)
339         {
340         rpc_t *rpc;
341         ULONG status;
342         TIMING_START();
343
344         rpc = rpc_create(0);
345
346         rpc_marshal_long(rpc, RPC_CREATE);
347         rpc_marshal_long(rpc, attribs);
348         rpc_marshal_longlong(rpc, alloc);
349         rpc_marshal_long(rpc, access);
350
351         rpc_queue_bulk(rpc, (void*)name, (wcslen(name)+1)*sizeof(wchar_t), NULL, 0);
352         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
353                 {
354                 rpc_cancel(rpc);
355                 rpt0(("cancel", "cancel create"));
356                 return IFSL_RPC_TIMEOUT;
357                 }
358
359         rpc_unmarshal_long(rpc, &status);
360         rpc_unmarshal_long(rpc, granted);
361         rpc_unmarshal_long(rpc, fid);
362
363         rpc_destroy(rpc);
364         TIMING_END("create");
365         return status;
366         }
367
368 uc_stat(ULONG fid, ULONG *attribs, LARGE_INTEGER *size, LARGE_INTEGER *creation, LARGE_INTEGER *access, LARGE_INTEGER *change, LARGE_INTEGER *written)
369         {
370         rpc_t *rpc;
371         ULONG status;
372         TIMING_START();
373
374         rpc = rpc_create(0);
375
376         rpc_marshal_long(rpc, RPC_STAT);
377         rpc_marshal_long(rpc, fid);
378
379         rpc_queue(rpc);
380         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
381                 {
382                 rpc_cancel(rpc);
383                 rpt0(("cancel", "cancel stat"));
384                 return IFSL_RPC_TIMEOUT;
385                 }
386
387         rpc_unmarshal_long(rpc, &status);
388         rpc_unmarshal_long(rpc, attribs);
389         rpc_unmarshal_longlong(rpc, size);
390         rpc_unmarshal_longlong(rpc, creation);
391         rpc_unmarshal_longlong(rpc, access);
392         rpc_unmarshal_longlong(rpc, change);
393         rpc_unmarshal_longlong(rpc, written);
394
395         rpc_destroy(rpc);
396         TIMING_END("stat");
397         return status;
398         }
399
400 uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER access, LARGE_INTEGER change, LARGE_INTEGER written)
401         {
402         rpc_t *rpc;
403         ULONG status;
404         TIMING_START();
405
406         rpc = rpc_create(0);
407
408         rpc_marshal_long(rpc, RPC_SETINFO);
409         rpc_marshal_long(rpc, fid);
410         rpc_marshal_long(rpc, attribs);
411         rpc_marshal_longlong(rpc, creation);
412         rpc_marshal_longlong(rpc, access);
413         rpc_marshal_longlong(rpc, change);
414         rpc_marshal_longlong(rpc, written);
415
416
417         rpc_queue(rpc);
418         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
419                 {
420                 rpc_cancel(rpc);
421                 rpt0(("cancel", "cancel setinfo"));
422                 return IFSL_RPC_TIMEOUT;
423                 }
424
425         rpc_unmarshal_long(rpc, &status);
426
427         rpc_destroy(rpc);
428         TIMING_END("setinfo");
429         return status;
430         }
431
432 uc_trunc(ULONG fid, LARGE_INTEGER size)
433         {
434         rpc_t *rpc;
435         ULONG status;
436         TIMING_START();
437
438         rpc = rpc_create(0);
439
440         rpc_marshal_long(rpc, RPC_TRUNC);
441         rpc_marshal_long(rpc, fid);
442         rpc_marshal_longlong(rpc, size);
443
444         rpc_queue(rpc);
445         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
446                 {
447                 rpc_cancel(rpc);
448                 rpt0(("cancel", "cancel trunc"));
449                 return IFSL_RPC_TIMEOUT;
450                 }
451
452         rpc_unmarshal_long(rpc, &status);
453
454         rpc_destroy(rpc);
455         TIMING_END("trunc");
456         return status;
457         }
458
459 uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
460         {
461         rpc_t *rpc;
462         ULONG status;
463         TIMING_START();
464
465         rpc = rpc_create(0);
466
467         rpc_marshal_long(rpc, RPC_READ);
468         rpc_marshal_long(rpc, fid);
469         rpc_marshal_longlong(rpc, offset);
470         rpc_marshal_long(rpc, length);
471
472         rpc_queue_bulk(rpc, NULL, 0, data, length);
473         if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
474                 {
475                 rpc_cancel(rpc);
476                 rpt0(("cancel", "cancel read"));
477                 return IFSL_RPC_TIMEOUT;
478                 }
479
480         rpc_unmarshal_long(rpc, &status);
481         rpc_unmarshal_long(rpc, read);
482
483         rpc_destroy(rpc);
484         TIMING_END("read");
485         return status;
486         }
487
488 /*uc_read_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, MDL *data)
489         {
490         rpc_t *rpc;
491         ULONG status;
492         TIMING_START();
493
494         rpc = rpc_create(0);
495
496         rpc_marshal_long(rpc, RPC_READ_BULK);
497         rpc_marshal_long(rpc, fid);
498         rpc_marshal_longlong(rpc, offset);
499         rpc_marshal_long(rpc, length);
500
501         rpc_queue_bulk_mdl(rpc, data);
502         if (!rpc_wait(rpc, 1))
503                 {
504                 rpc_cancel(rpc);
505                 rpt0(("cancel", "cancel read mdl"));
506                 return IFSL_RPC_TIMEOUT;
507                 }
508
509         rpc_unmarshal_long(rpc, &status);
510         rpc_unmarshal_long(rpc, read);
511
512         rpc_destroy(rpc);
513         TIMING_END("read_mdl");
514         return status;
515         }*/
516
517 uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *data)
518         {
519         rpc_t *rpc;
520         ULONG status;
521         TIMING_START();
522
523         rpc = rpc_create(0);
524
525         rpc_marshal_long(rpc, RPC_WRITE);
526         rpc_marshal_long(rpc, fid);
527         rpc_marshal_longlong(rpc, offset);
528         rpc_marshal_long(rpc, length);
529
530         rpc_queue_bulk(rpc, data, length, NULL, 0);
531         if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
532                 {
533                 rpc_cancel(rpc);
534                 rpt0(("cancel", "cancel write"));
535                 return IFSL_RPC_TIMEOUT;
536                 }
537
538         rpc_unmarshal_long(rpc, &status);
539         rpc_unmarshal_long(rpc, written);
540
541         rpc_destroy(rpc);
542         TIMING_END("write");
543         return status;
544         }
545
546 /*uc_write_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, MDL *data)
547         {
548         rpc_t *rpc;
549         ULONG status;
550         TIMING_START();
551
552         rpc = rpc_create(0);
553
554         rpc_marshal_long(rpc, RPC_WRITE_BULK);
555         rpc_marshal_long(rpc, fid);
556         rpc_marshal_longlong(rpc, offset);
557         rpc_marshal_long(rpc, length);
558
559         rpc_queue_bulk_mdl(rpc, data);
560         if (!rpc_wait(rpc, 1))
561                 {
562                 rpc_cancel(rpc);
563                 rpt0(("cancel", "cancel write mdl"));
564                 return IFSL_RPC_TIMEOUT;
565                 }
566
567         rpc_unmarshal_long(rpc, &status);
568         rpc_unmarshal_long(rpc, written);
569
570         rpc_destroy(rpc);
571         TIMING_END("write_mdl");
572         return status;
573         }*/
574
575 uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char *data, ULONG *len)
576         {
577         rpc_t *rpc;
578         ULONG status;
579         TIMING_START();
580
581         rpc = rpc_create(0);
582
583         rpc_marshal_long(rpc, RPC_READDIR);
584         rpc_marshal_long(rpc, fid);
585         rpc_marshal_longlong(rpc, cookie_in);
586         rpc_marshal_wstr(rpc, filter);
587         rpc_marshal_long(rpc, *len);
588
589         rpc_queue_bulk(rpc, NULL, 0, data, *len);
590         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
591                 {
592                 rpc_cancel(rpc);
593                 rpt0(("cancel", "cancel readdir"));
594                 return IFSL_RPC_TIMEOUT;
595                 }
596
597         rpc_unmarshal_long(rpc, &status);
598         rpc_unmarshal_long(rpc, count);
599         rpc_unmarshal_long(rpc, len);
600
601         rpc_destroy(rpc);
602         TIMING_END("readdir");
603         return status;
604         }
605
606 uc_close(ULONG fid)
607         {
608         rpc_t *rpc;
609         ULONG status;
610         TIMING_START();
611
612         rpc = rpc_create(0);
613
614         rpc_marshal_long(rpc, RPC_CLOSE);
615         rpc_marshal_long(rpc, fid);
616
617         rpc_queue(rpc);
618         if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
619                 {
620                 rpc_cancel(rpc);
621                 rpt0(("cancel", "cancel close"));
622                 return IFSL_RPC_TIMEOUT;
623                 }
624
625         rpc_unmarshal_long(rpc, &status);
626
627         rpc_destroy(rpc);
628         TIMING_END("close");
629         return status;
630         }
631
632 uc_unlink(WCHAR *name)
633         {
634         rpc_t *rpc;
635         ULONG status;
636         TIMING_START();
637
638         rpc = rpc_create(0);
639
640         rpc_marshal_long(rpc, RPC_UNLINK);
641         rpc_marshal_wstr(rpc, name);
642
643         rpc_queue(rpc);
644         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
645                 {
646                 rpc_cancel(rpc);
647                 rpt0(("cancel", "cancel unlink"));
648                 return IFSL_RPC_TIMEOUT;
649                 }
650
651         rpc_unmarshal_long(rpc, &status);
652
653         rpc_destroy(rpc);
654         TIMING_END("unlink");
655         return status;
656         }
657
658 uc_ioctl_write(ULONG length, char *data, ULONG *key)
659         {
660         rpc_t *rpc;
661         ULONG status;
662         TIMING_START();
663
664         rpc = rpc_create(0);
665
666         rpc_marshal_long(rpc, RPC_IOCTL_WRITE);
667         rpc_marshal_long(rpc, length);
668
669         rpc_queue_bulk(rpc, data, length, NULL, 0);
670         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
671                 {
672                 rpc_cancel(rpc);
673                 rpt0(("cancel", "cancel ioctl write"));
674                 return IFSL_RPC_TIMEOUT;
675                 }
676
677         rpc_unmarshal_long(rpc, &status);
678         rpc_unmarshal_long(rpc, key);
679
680         rpc_destroy(rpc);
681         TIMING_END("ioctl_write");
682         return status;
683         }
684
685 uc_ioctl_read(ULONG key, ULONG *length, char *data)
686         {
687         rpc_t *rpc;
688         ULONG status;
689         TIMING_START();
690
691         rpc = rpc_create(0);
692
693         rpc_marshal_long(rpc, RPC_IOCTL_READ);
694         rpc_marshal_long(rpc, key);
695
696         rpc_queue_bulk(rpc, NULL, 0, data, *length);
697         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
698                 {
699                 rpc_cancel(rpc);
700                 rpt0(("cancel", "cancel ioctl read"));
701                 return IFSL_RPC_TIMEOUT;
702                 }
703
704         rpc_unmarshal_long(rpc, &status);
705         rpc_unmarshal_long(rpc, length);
706
707         rpc_destroy(rpc);
708         TIMING_END("ioctl_read");
709         return status;
710         }
711
712 uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fid)
713         {
714         rpc_t *rpc;
715         ULONG status;
716         TIMING_START();
717
718         rpc = rpc_create(0);
719
720         rpc_marshal_long(rpc, RPC_RENAME);
721         rpc_marshal_long(rpc, fid);
722         rpc_marshal_wstr(rpc, curr);
723         rpc_marshal_wstr(rpc, new_dir);
724         rpc_marshal_wstr(rpc, new_name);
725
726         rpc_queue(rpc);
727         if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
728                 {
729                 rpc_cancel(rpc);
730                 rpt0(("cancel", "cancel rename"));
731                 return IFSL_RPC_TIMEOUT;
732                 }
733
734         rpc_unmarshal_long(rpc, &status);
735         rpc_unmarshal_long(rpc, new_fid);
736
737         rpc_destroy(rpc);
738         TIMING_END("rename");
739         return status;
740         }
741 #endif
742
743
744 /* downcall stubs */
745 #ifndef RPC_KERN
746 dc_break_callback(ULONG fid)
747         {
748         rpc_t *rpc;
749         ULONG status;
750
751         rpc = rpc_create(0);
752
753         rpc_marshal_long(rpc, RPC_BREAK_CALLBACK);
754         rpc_marshal_long(rpc, fid);
755         if (!rpc_transact(rpc))
756                 {
757                 rpc_destroy(rpc);
758                 return IFSL_GENERIC_FAILURE;
759                 }
760         rpc_unmarshal_long(rpc, &status);
761         rpc_destroy(rpc);
762         return status;
763         }
764 #endif
765
766
767 /* rpc packing function */
768 rpc_marshal_long(rpc_t *rpc, ULONG data)
769         {
770         memcpy(rpc->out_pos, &data, sizeof(ULONG));
771         rpc->out_pos += sizeof(ULONG);
772         return 0;
773         }
774
775 rpc_marshal_longlong(rpc_t *rpc, LARGE_INTEGER data)
776         {
777         memcpy(rpc->out_pos, &data, sizeof(LARGE_INTEGER));
778         rpc->out_pos += sizeof(LARGE_INTEGER);
779         return 0;
780         }
781
782 rpc_marshal_wstr(rpc_t *rpc, WCHAR *str)
783         {
784         long len;
785         len = wcslen(str);
786         rpc_marshal_long(rpc, len);
787         memcpy(rpc->out_pos, str, len*sizeof(WCHAR));
788         rpc->out_pos += len*sizeof(WCHAR);
789         return 0;
790         }
791
792
793 rpc_unmarshal_long(rpc_t *rpc, ULONG *data)
794         {
795         memcpy(data, rpc->in_pos, sizeof(ULONG));
796         rpc->in_pos += sizeof(ULONG);
797         return 0;
798         }
799
800 rpc_unmarshal_longlong(rpc_t *rpc, LARGE_INTEGER *data)
801         {
802         memcpy(data, rpc->in_pos, sizeof(LARGE_INTEGER));
803         rpc->in_pos += sizeof(LARGE_INTEGER);
804         return 0;
805         }
806
807 rpc_unmarshal_wstr(rpc_t *rpc, WCHAR *str)//, int len)
808         {
809         long len;
810         rpc_unmarshal_long(rpc, &len);
811         memcpy(str, rpc->in_pos, len*sizeof(WCHAR));
812         rpc->in_pos += len*sizeof(WCHAR);
813         str[len] = L'\0';
814         return 0;
815         }
816
817
818 /* kernel-queue management functions */
819 #ifdef RPC_KERN
820 rpc_t *rpc_find(int id)
821         {
822         rpc_t *curr;
823
824         curr = rpc_list_head;
825         while (curr)
826                 {
827                 if (curr->key == id && curr->status != 0)
828                         return curr;
829                 curr = curr->next;
830                 }
831         return NULL;
832         }
833
834 rpc_t *rpc_upgrade(rpc_t *rpc, int old_status, int new_status)
835         {
836         rpc_t *curr;
837
838         if (rpc)
839                 {
840                 ASSERT(!old_status || rpc_find(rpc->key));
841                 if (old_status != -1 && rpc->status != old_status)
842                         return NULL;
843                 curr = rpc;
844                 }
845         else
846                 {
847                 curr = rpc_list_head;
848                 while (curr)
849                         {
850                         if (old_status == -1 || curr->status == old_status)
851                                 break;
852                         curr = curr->next;
853                         }
854                 }
855
856         if (!curr)
857                 return NULL;
858
859         ASSERT(old_status == -1 || curr->status == old_status);
860         curr->status = new_status;
861
862         return curr;
863         }
864
865 rpc_queue(rpc_t *rpc)
866         {
867         int ret;
868
869         ifs_lock_rpcs();
870
871         KeInitializeEvent(&rpc->ev, NotificationEvent, FALSE);
872         ret = (rpc_upgrade(rpc, 1, 2) != NULL);
873         KeSetEvent(&comExt->outEvent, 0, FALSE);
874
875         ifs_unlock_rpcs();
876
877         return ret;
878         }
879
880 rpc_cancel(rpc_t *rpc)
881         {
882         rpc_destroy(rpc);
883         //ExAcquireFastMutex(&ext->inLock);
884         /*ifs_lock_rpcs();
885         if (rpc_upgrade(rpc, -1, 0))
886                 rpc_destroy(rpc);
887         ifs_unlock_rpcs();*/
888         //RtlDeleteElementGenericTable(&ext->inTable, (void*)&rpc);
889         //ExReleaseFastMutex(&ext->inLock);
890         }
891
892 rpc_shutdown()
893         {
894         rpc_t *curr, *next;
895
896         ifs_lock_rpcs();
897
898         curr = rpc_list_head;
899         while (curr)
900                 {
901                 next = curr->next;
902                 ExFreePoolWithTag(curr, 0x1234);
903                 curr = next;
904                 }
905         rpc_list_head = NULL;
906
907         ifs_unlock_rpcs();
908         }
909
910 rpc_wait(rpc_t *rpc, BOOLEAN long_op)
911         {
912         NTSTATUS ret;
913         LARGE_INTEGER timeout;
914         //p->FsContext = (ULONG)&ev;
915
916         if (long_op)
917                 timeout.QuadPart = -600000000L;         /* 60 seconds 60L*1000000L */
918         else
919                 timeout.QuadPart = -200000000L;         /* 20 seconds 20L*1000000L */
920
921         do
922                 ret = KeWaitForSingleObject(&rpc->ev, Executive, KernelMode, FALSE, &timeout);
923         while (ret != STATUS_SUCCESS);// && ret != STATUS_TIMEOUT);
924
925         /*if (KeReadStateEvent(&rpc->ev) == 0)
926                 _asm int 3;*/
927         if (rpc->status == 5)
928                 return 0;
929
930         if (ret == STATUS_SUCCESS)
931                 return 1;
932         _asm int 3;
933         return 0;
934         }
935
936 rpc_queue_bulk(rpc_t *rpc, char *out_bulk, ULONG out_len, char *in_bulk, ULONG in_len)
937         {
938         rpc->bulk_out = out_bulk;
939         *rpc->bulk_out_len = out_len;
940         rpc->bulk_in = in_bulk;
941         rpc->bulk_in_max = in_len;
942         return rpc_queue(rpc);
943         }
944
945 /*rpc_queue_bulk_mdl(rpc_t *rpc, MDL *bulk)
946         {
947         rpc->bulk_mdl = bulk;
948         *rpc->bulk_out_len = 0xFFFFFFFC;
949         rpc->bulk_in = 0;
950         return rpc_queue(rpc);
951         }*/
952
953 rpc_get_len(rpc_t *rpc)
954         {
955         if (*rpc->bulk_out_len != 0xFFFFFFFC)
956                 return rpc->out_pos - rpc->out_buf + *rpc->bulk_out_len + sizeof(ULONG);
957         else
958                 return rpc->out_pos - rpc->out_buf + sizeof(ULONG);
959         }
960
961 rpc_send(char *out_buf, int out_len, int *out_written)
962         {
963         rpc_t *rpc;
964         int ret, mdl;
965         ULONG header_len;
966
967         restart:
968
969         ifs_lock_rpcs();
970         rpc = rpc_upgrade(NULL, 2, 3);
971
972         if (!rpc)
973                 {
974                 ifs_unlock_rpcs();
975                 return 0;
976                 }
977
978         if (rpc_get_len(rpc) > out_len)
979                 {
980                 //_asm int 3;
981                 ifs_unlock_rpcs();
982                 rpt0(("cancel", "cancel on send"));
983                 rpc_upgrade(rpc, -1, 5);
984                 KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);   /* move to rpc_ fn */
985                 //rpc_cancel(rpc);
986                 goto restart;//return 0;
987                 }
988
989
990
991         /*mdl = (*rpc->bulk_out_len == 0xFFFFFFFC);
992
993         if (mdl)
994                 *rpc->bulk_out_len = 0;*/
995
996         header_len = rpc->out_pos - rpc->out_buf;
997         RtlCopyMemory(out_buf, rpc->out_buf, header_len);
998
999         //if (!mdl)
1000                 {
1001                 if (*rpc->bulk_out_len && rpc->bulk_out)
1002                         RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
1003                 *out_written = header_len + *rpc->bulk_out_len;
1004                 }
1005         #if 0
1006         else
1007                 {
1008                 if (rpc->bulk_mdl)
1009                         {
1010                         void *ptr;
1011                         //_asm int 3;
1012         #if 0
1013                         try
1014                                 {
1015                                 _asm int 3;
1016                                 MmProbeAndLockPages(rpc->bulk_mdl, UserMode, IoModifyAccess);
1017                                 }
1018                         except (EXCEPTION_EXECUTE_HANDLER)
1019                                 {
1020                                 _asm int 3;
1021                                 }
1022         #endif
1023                         try
1024                                 {
1025                                 rpc->bulk_out = MmMapLockedPagesSpecifyCache(rpc->bulk_mdl, UserMode, MmNonCached, NULL, FALSE, NormalPagePriority);
1026                                 }
1027                         except (EXCEPTION_EXECUTE_HANDLER)
1028                                 {
1029                                 PMDL remap;
1030                                 void *ptr;
1031                                 _asm int 3;
1032                                 ptr = ExAllocatePool(PagedPool, MmGetMdlByteCount(rpc->bulk_mdl));
1033                                 remap = IoAllocateMdl(ptr, MmGetMdlByteCount(rpc->bulk_mdl), FALSE, TRUE, NULL);
1034                                 MmProbeAndLockPages(remap, UserMode, IoModifyAccess);
1035                                 rpc->bulk_out = MmMapLockedPagesSpecifyCache(remap, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
1036                                 _asm int 3;
1037                                 rpc->bulk_out = MmGetSystemAddressForMdlSafe(rpc->bulk_mdl, NormalPagePriority);
1038                                 MmUnmapLockedPages(rpc->bulk_out, rpc->bulk_mdl);
1039                                 rpc->bulk_out = MmMapLockedPagesSpecifyCache(rpc->bulk_mdl, UserMode, MmNonCached, NULL, FALSE, NormalPagePriority);
1040
1041                                 remap = IoAllocateMdl(rpc->bulk_out, MmGetMdlByteCount(rpc->bulk_mdl), FALSE, TRUE, NULL);
1042                                 remap->Process = (void*)PsGetCurrentProcess();
1043                                 MmBuildMdlForNonPagedPool(remap);
1044                                 //MmProbeAndLockPages(remap, UserMode, IoModifyAccess);
1045                                 rpc->bulk_out = MmMapLockedPagesSpecifyCache(remap, UserMode, MmNonCached, (void*)0x01111111, FALSE, NormalPagePriority);
1046                                 /*ifs_unlock_rpcs();
1047                                 rpc_upgrade(rpc, -1, 5);
1048                                 KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);
1049                                 //rpc_cancel(rpc);
1050                                 goto restart;//return 0;*/
1051                                 }
1052                         ptr = rpc->bulk_out;
1053                         RtlCopyMemory(out_buf + header_len, &ptr, sizeof(ptr));
1054                         }
1055
1056                 *rpc->bulk_out_len = 0xFFFFFFFC;
1057                 *out_written = header_len + sizeof(void*);
1058                 }
1059         #endif
1060
1061         ifs_unlock_rpcs();
1062         return (*out_written != 0);
1063         }
1064
1065 #if 0
1066 rpc_send_reg(rpc_t *rpc, char *out_buf)
1067         {
1068         ULONG header_len;
1069
1070         header_len = rpc->out_pos - rpc->out_buf;
1071         RtlCopyMemory(out_buf, rpc->out_buf, header_len);
1072
1073         if (rpc->bulk_out_len && rpc->bulk_out)
1074                 RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
1075         return header_len + *rpc->bulk_out_len;
1076         }
1077 #endif
1078 #endif
1079
1080
1081 /* rpc library api */
1082 #ifdef RPC_KERN
1083 rpc_recv(char *in_buf, ULONG len)
1084         {
1085         ULONG key, header_size;
1086         char *alloc;
1087         rpc_t *rpc;
1088
1089         ifs_lock_rpcs();
1090
1091         rpc = rpc_find(*(ULONG*)in_buf);
1092         if (!rpc)
1093                 {
1094                 //_asm int 3;
1095                 ifs_unlock_rpcs();
1096                 return -1;
1097                 }
1098
1099         //_asm int 3;
1100         /*if (*rpc->bulk_out_len == 0xFFFFFFFC)
1101                 {
1102                 ASSERT(rpc->bulk_out);
1103                 MmUnmapLockedPages(rpc->bulk_out, rpc->bulk_mdl);
1104         //      MmUnlockPages(rpc->bulk_mdl);
1105                 }*/
1106
1107         alloc = rpc->in_buf;
1108         rpc->in_buf = rpc->in_pos = in_buf;
1109         rpc_unmarshal_long(rpc, &key);
1110         ASSERT(key == rpc->key);
1111         rpc_unmarshal_long(rpc, &rpc->bulk_in_len);
1112
1113         rpc->in_buf = rpc->in_pos = alloc;
1114         header_size = len - rpc->bulk_in_len;
1115         ASSERT(header_size < 4096);
1116         RtlCopyMemory(rpc->in_buf, in_buf + 2*sizeof(ULONG), header_size - 2*sizeof(ULONG));
1117         //if (*rpc->bulk_out_len != 0xFFFFFFFC)
1118                 {
1119                 if (rpc->bulk_in_len && rpc->bulk_in)
1120                         {
1121                         ASSERT(rpc->bulk_in_len <= rpc->bulk_in_max);
1122                         //_asm int 3;
1123                         RtlCopyMemory(rpc->bulk_in, in_buf + header_size, rpc->bulk_in_len);//len - header_size - 2*sizeof(ULONG));
1124                         }
1125                 }
1126
1127         KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);
1128         ifs_unlock_rpcs();
1129         return 0;
1130         }
1131
1132 rpc_call(ULONG in_len, char *in_buf, ULONG out_max, char *out_buf, ULONG *out_len)
1133         {
1134         long rpc_code;
1135         ULONG status;
1136         WCHAR name[1024];
1137         ULONG key, fid;
1138         LARGE_INTEGER user_id;
1139         rpc_t rpc;
1140
1141         rpc.in_buf = rpc.in_pos = in_buf;
1142         rpc.out_buf = rpc.out_pos = out_buf;
1143
1144         rpc_unmarshal_long(&rpc, &key);
1145         rpc_unmarshal_long(&rpc, &rpc_code);
1146
1147         switch (rpc_code)
1148                 {
1149                 case RPC_BREAK_CALLBACK:
1150                         rpc_unmarshal_long(&rpc, &fid);
1151                         status = dc_break_callback(fid);
1152                         rpc_marshal_long(&rpc, status);
1153                         break;
1154                 }
1155         *out_len = rpc.out_pos - rpc.out_buf;
1156         return 0;
1157         //ifs_ImpersonateClient(user_id);
1158         }
1159 #endif
1160
1161 #ifndef RPC_KERN
1162 rpc_parse(rpc_t *rpc)
1163         {
1164         long rpc_code;
1165         ULONG status;
1166         WCHAR name[1024];
1167         ULONG key;
1168         LARGE_INTEGER user_id;
1169
1170         rpc_unmarshal_long(rpc, &key);
1171         rpc_unmarshal_long(rpc, &rpc->bulk_in_len);
1172         rpc_unmarshal_longlong(rpc, &user_id);
1173         rpc_unmarshal_long(rpc, &rpc_code);
1174
1175         ifs_ImpersonateClient(user_id);
1176
1177         rpc_marshal_long(rpc, key);
1178         rpc->bulk_out_len = (ULONG*)rpc->out_pos;
1179         rpc_marshal_long(rpc, 0);
1180
1181         switch (rpc_code)
1182                 {
1183                 case RPC_NAMEI:
1184                         {
1185                         ULONG fid, length;
1186                         char *data;
1187                         //rpc_unmarshal_wstr(rpc, name);
1188                         rpc_unmarshal_long(rpc, &length);
1189                         //data = *((char**)rpc->in_pos);
1190                         data = rpc->in_pos;
1191                         status = uc_namei((WCHAR*)data, &fid);
1192                         //status = uc_namei(name, &fid);
1193                         rpc_marshal_long(rpc, status);          
1194                         rpc_marshal_long(rpc, fid);             
1195                         }
1196                         break;
1197                 case RPC_CHECK_ACCESS:
1198                         {
1199                         ULONG fid, access, granted;
1200                         rpc_unmarshal_long(rpc, &fid);
1201                         rpc_unmarshal_long(rpc, &access);
1202                         status = uc_check_access(fid, access, &granted);
1203                         rpc_marshal_long(rpc, status);          
1204                         rpc_marshal_long(rpc, granted);
1205                         }
1206                         break;
1207                 case RPC_CREATE:
1208                         {
1209                         LARGE_INTEGER alloc;
1210                         ULONG access, granted, fid, attribs;
1211                         char *data;
1212
1213                         rpc_unmarshal_long(rpc, &attribs);
1214                         rpc_unmarshal_longlong(rpc, &alloc);
1215                         rpc_unmarshal_long(rpc, &access);
1216                         //rpc_unmarshal_wstr(rpc, name);
1217                         data = rpc->in_pos;
1218                         status = uc_create((WCHAR*)data, attribs, alloc, access, &granted, &fid);
1219                         rpc_marshal_long(rpc, status);
1220                         rpc_marshal_long(rpc, granted);
1221                         rpc_marshal_long(rpc, fid);
1222                         }
1223                         break;
1224                 case RPC_STAT:
1225                         {
1226                         ULONG fid, attribs;
1227                         LARGE_INTEGER size, creation, access, change, written;
1228                         rpc_unmarshal_long(rpc, &fid);
1229                         status = uc_stat(fid, &attribs, &size, &creation, &access, &change, &written);
1230                         rpc_marshal_long(rpc, status);
1231                         rpc_marshal_long(rpc, attribs);
1232                         rpc_marshal_longlong(rpc, size);
1233                         rpc_marshal_longlong(rpc, creation);
1234                         rpc_marshal_longlong(rpc, access);
1235                         rpc_marshal_longlong(rpc, change);
1236                         rpc_marshal_longlong(rpc, written);
1237                         }
1238                         break;
1239                 case RPC_READ:
1240                         {
1241                         ULONG fid, length, read;
1242                         LARGE_INTEGER offset;
1243                         char *data, *save;
1244                         rpc_unmarshal_long(rpc, &fid);
1245                         rpc_unmarshal_longlong(rpc, &offset);
1246                         rpc_unmarshal_long(rpc, &length);
1247                         save = rpc->out_pos;
1248                         rpc_marshal_long(rpc, 0);
1249                         rpc_marshal_long(rpc, 0);
1250                         data = rpc->out_pos;
1251                         rpc->out_pos = save;
1252                         status = uc_read(fid, offset, length, &read, data);
1253                         rpc_marshal_long(rpc, status);
1254                         rpc_marshal_long(rpc, read);
1255                         rpc->out_pos += read;
1256                         *rpc->bulk_out_len = read;
1257                         }
1258                         break;
1259         /*      case RPC_READ_BULK:
1260                         {
1261                         ULONG fid, length, read;
1262                         LARGE_INTEGER offset;
1263                         char *data, *save;
1264                         rpc_unmarshal_long(rpc, &fid);
1265                         rpc_unmarshal_longlong(rpc, &offset);
1266                         rpc_unmarshal_long(rpc, &length);
1267                         data = *((char**)rpc->in_pos);
1268                         status = uc_read(fid, offset, length, &read, data);
1269                         rpc_marshal_long(rpc, status);
1270                         rpc_marshal_long(rpc, read);
1271                         *rpc->bulk_out_len = 0;
1272                         }
1273                         break;*/
1274                 case RPC_WRITE:
1275                         {
1276                         ULONG fid, length, written;
1277                         LARGE_INTEGER offset;
1278                         char *data;
1279                         rpc_unmarshal_long(rpc, &fid);
1280                         rpc_unmarshal_longlong(rpc, &offset);
1281                         rpc_unmarshal_long(rpc, &length);
1282                         data = rpc->in_pos;
1283                         status = uc_write(fid, offset, length, &written, data);
1284                         rpc_marshal_long(rpc, status);
1285                         rpc_marshal_long(rpc, written);
1286                         }
1287                         break;
1288         /*      case RPC_WRITE_BULK:
1289                         {
1290                         ULONG fid, length, written;
1291                         LARGE_INTEGER offset;
1292                         char *data;
1293                         //_asm int 3;
1294                         rpc_unmarshal_long(rpc, &fid);
1295                         rpc_unmarshal_longlong(rpc, &offset);
1296                         rpc_unmarshal_long(rpc, &length);
1297                         data = *((char**)rpc->in_pos);
1298                         status = uc_write(fid, offset, length, &written, data);
1299                         rpc_marshal_long(rpc, status);
1300                         rpc_marshal_long(rpc, written);
1301                         }
1302                         break;*/
1303                 case RPC_TRUNC:
1304                         {
1305                         ULONG fid;
1306                         LARGE_INTEGER size;
1307                         rpc_unmarshal_long(rpc, &fid);
1308                         rpc_unmarshal_longlong(rpc, &size);
1309                         status = uc_trunc(fid, size);
1310                         rpc_marshal_long(rpc, status);
1311                         }
1312                         break;
1313                 case RPC_SETINFO:
1314                         {
1315                         ULONG fid, attribs;
1316                         LARGE_INTEGER creation, access, change, written;
1317                         rpc_unmarshal_long(rpc, &fid);
1318                         rpc_unmarshal_long(rpc, &attribs);
1319                         rpc_unmarshal_longlong(rpc, &creation);
1320                         rpc_unmarshal_longlong(rpc, &access);
1321                         rpc_unmarshal_longlong(rpc, &change);
1322                         rpc_unmarshal_longlong(rpc, &written);
1323                         status = uc_setinfo(fid, attribs, creation, access, change, written);
1324                         rpc_marshal_long(rpc, status);
1325                         }
1326                         break;
1327                 case RPC_READDIR:
1328                         {
1329                         ULONG fid, count, len;
1330                         LARGE_INTEGER cookie_in;
1331                         char *data, *save;
1332                         rpc_unmarshal_long(rpc, &fid);
1333                         rpc_unmarshal_longlong(rpc, &cookie_in);
1334                         rpc_unmarshal_wstr(rpc, name);
1335                         rpc_unmarshal_long(rpc, &len);
1336                         save = rpc->out_pos;
1337                         rpc_marshal_long(rpc, 0);
1338                         rpc_marshal_long(rpc, 0);
1339                         rpc_marshal_long(rpc, 0);
1340                         data = rpc->out_pos;
1341                         rpc->out_pos = save;
1342                         status = uc_readdir(fid, cookie_in, name, &count, data, &len);
1343                         rpc_marshal_long(rpc, status);
1344                         rpc_marshal_long(rpc, count);
1345                         rpc_marshal_long(rpc, len);
1346                         rpc->out_pos += len;
1347                         *rpc->bulk_out_len = len;
1348                         }
1349                         break;
1350                 case RPC_CLOSE:
1351                         {
1352                         ULONG fid;
1353                         rpc_unmarshal_long(rpc, &fid);
1354                         status = uc_close(fid);
1355                         rpc_marshal_long(rpc, status);
1356                         }
1357                         break;
1358                 case RPC_UNLINK:
1359                         {
1360                         ULONG fid, unlink;
1361                         rpc_unmarshal_wstr(rpc, name);
1362                         status = uc_unlink(name);
1363                         rpc_marshal_long(rpc, status);
1364                         }
1365                         break;
1366                 case RPC_IOCTL_WRITE:
1367                         {
1368                         ULONG length, key;
1369                         rpc_unmarshal_long(rpc, &length);
1370                         status = uc_ioctl_write(length, rpc->in_pos, &key);
1371                         rpc_marshal_long(rpc, status);
1372                         rpc_marshal_long(rpc, key);
1373                         }
1374                         break;
1375                 case RPC_IOCTL_READ:
1376                         {
1377                         ULONG key, length;
1378                         char *save, *data;
1379                         rpc_unmarshal_long(rpc, &key);
1380                         save = rpc->out_pos;
1381                         rpc_marshal_long(rpc, 0);
1382                         rpc_marshal_long(rpc, 0);
1383                         data = rpc->out_pos;
1384                         rpc->out_pos = save;
1385                         status = uc_ioctl_read(key, &length, data);
1386                         rpc_marshal_long(rpc, status);
1387                         rpc_marshal_long(rpc, length);
1388                         rpc->out_pos += length;
1389                         *rpc->bulk_out_len = length;
1390                         }
1391                         break;
1392                 case RPC_RENAME:
1393                         {
1394                         ULONG fid, new_fid;
1395                         WCHAR curr[1024], new_dir[1024], new_name[1024];
1396                         rpc_unmarshal_long(rpc, &fid);
1397                         rpc_unmarshal_wstr(rpc, curr);
1398                         rpc_unmarshal_wstr(rpc, new_dir);
1399                         rpc_unmarshal_wstr(rpc, new_name);
1400                         status = uc_rename(fid, curr, new_dir, new_name, &new_fid);
1401                         rpc_marshal_long(rpc, status);
1402                         rpc_marshal_long(rpc, new_fid);
1403                         }
1404                         break;
1405                 }
1406         }
1407 #endif