07139f6e3e088f26ea5e6e70d1c0aadee24d48d7
[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