source: branches/samba-3.0/source/ndpsmb/ndpsmb.c@ 107

Last change on this file since 107 was 107, checked in by Paul Smedley, 18 years ago

Add configurable kerberos support for Netdrive plugin

  • Property svn:eol-style set to native
File size: 62.7 KB
Line 
1#define NDPL_LARGEFILES
2#define INCL_LONGLONG
3#include <ndextpl2.h>
4#include <smbwrp.h>
5#include <smbcd.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdarg.h>
9#include <time.h>
10
11
12#define NULL ((void *)0)
13
14void log(const char *fmt, ...)
15{
16 char *ndpsmb_debug = getenv("NDPSMB_DEBUG");
17
18 if (ndpsmb_debug != NULL)
19 {
20 FILE * logfile = NULL;
21 va_list args;
22 time_t t = time(NULL);
23 char timebuf[80] = {0};
24 strftime(timebuf,sizeof(timebuf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
25 logfile = fopen("smblog","a");
26 if (logfile == NULL)
27 {
28 DosBeep(400,400);
29 }
30 else
31 {
32 fprintf(logfile, "%s: (%02d) ", timebuf, _gettid());
33 va_start(args, fmt);
34 vfprintf(logfile, fmt, args);
35 va_end(args);
36 fclose(logfile);
37 }
38 }
39}
40
41int StrLen(char * s)
42{
43 char * p;
44 if (!s)
45 {
46 return 0;
47 }
48 for (p = s; *p; p++);
49 return (p - s);
50}
51
52char * StrNCat(char *dst, const char *src, int count)
53{
54 int i;
55 if (!dst || !src || count <= 0)
56 {
57 return dst;
58 }
59 for (i = 0; dst[i]; i++);
60 for (;i < count && *src; i++, src++)
61 {
62 dst[i] = *src;
63 }
64 dst[i] = 0;
65 return dst;
66}
67
68char * StrNCpy(char *dst, const char *src, int count)
69{
70 if (!dst || !src || count <= 0)
71 {
72 return dst;
73 }
74 *dst = 0;
75 return StrNCat(dst, src, count);
76}
77
78char * StrCpy(char *dst, const char *src)
79{
80 char * p;
81 if (!dst || !src)
82 {
83 return dst;
84 }
85 p = dst;
86 while (*p++ = *src++);
87 return dst;
88}
89
90char * StrCat(char *dst, const char *src)
91{
92 int i;
93 if (!dst || !src)
94 {
95 return dst;
96 }
97 for (i = 0; dst[i]; i++);
98 for (; *src; i++, src++)
99 {
100 dst[i] = *src;
101 }
102 dst[i] = 0;
103 return dst;
104}
105
106void * MemCpy(void * dst, const void * src, int len)
107{
108 int i;
109 if (!src || !dst || len <= 0)
110 {
111 return dst;
112 }
113 for (i = 0; i < len; i++)
114 {
115 ((char *)dst)[i] = ((char *)src)[i];
116 }
117 return dst;
118}
119
120void *MemSet(void *dst, char c, int len)
121{
122 int i;
123 if (!dst || len <= 0)
124 {
125 return dst;
126 }
127 for (i = 0; i < len; i++)
128 {
129 ((char *)dst)[i] = c;
130 }
131 return dst;
132}
133
134/* uppercased type of resource */
135const char *NdpTypes[] =
136{
137 "SMBFS",
138 NULL
139}
140;
141
142/* Properties of supported resource types */
143
144/* Properties of resource */
145static const NDPROPERTYINFO smbProperties[] =
146{
147 {ND_PROP_STRING, 0, "WORKGROUP", ""},
148 {ND_PROP_STRING, 0, "SERVER", ""},
149 {ND_PROP_STRING, 0, "SHARE", ""},
150 {ND_PROP_STRING, 0, "USER", "guest"},
151 {ND_PROP_STRING, 0, "PASSWORD", ""},
152 {ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
153 { ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
154 { ND_PROP_ULONG, 0, "MEMLEN", "2"},
155 {ND_PROP_STRING, 0, "LOGFILE", ""},
156 { ND_PROP_ULONG, 0, "LOGLEVEL", "0"},
157 { ND_PROP_ULONG, 0, "EASUPPORT", "1"},
158 { ND_PROP_ULONG, 0, "KRB5SUPPORT", "1"},
159 {ND_PROP_STRING, 0, NULL, NULL}
160};
161
162
163/* Exported array of properties */
164const NDPROPERTYINFO *NdpPropertiesInfo[] =
165{
166 smbProperties
167};
168
169
170static PLUGINHELPERTABLE2L *ph;
171static int ifL;
172
173int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
174{
175 int rc;
176 HPIPE pipe;
177 unsigned long action;
178 ph = pPHT;
179 ifL = 0;
180/*
181 if (ph->cb < sizeof (PLUGINHELPERTABLE2))
182 {
183 return ERROR_INVALID_FUNCTION;
184 }
185*/
186 if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
187 {
188 ifL = 1;
189 }
190 log("Working with %s bit fileio NDFS\n", ifL ? "64" : "32");
191 return NO_ERROR;
192}
193
194
195int APIENTRY NdpPluginFree (void)
196{
197 return NO_ERROR;
198}
199
200typedef struct _Resource
201{
202 /* NetDrive information */
203 NDPROPERTYHANDLE properties; /* access handle for the properties */
204 int rootlevel;
205 unsigned long memlen;
206 unsigned long objany;
207 smbwrp_server srv;
208 char logfile[CCHMAXPATH + 1];
209 char loglevel;
210 int easupport;
211 int krb5support;
212} Resource;
213
214typedef struct _Connection
215{
216 Resource *pRes;
217 HPIPE pipe;
218 char * mem;
219 int clientpid;
220 int rc;
221 smbwrp_server srv;
222 smbwrp_file file;
223} Connection;
224
225int openpipe(Resource * pRes, HPIPE * ppipe)
226{
227 HPIPE pipe = 0;
228 unsigned long rc = 0, action;
229
230 if (!pRes)
231 {
232 return ERROR_INVALID_PARAMETER;
233 }
234
235 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
236 log("DosOpen1 rc %d\n", rc);
237 if (rc)
238 {
239 unsigned long sid = 0, pid = 0;
240 STARTDATA sd;
241 char params[CCHMAXPATH * 2] = {0};
242
243 MemSet(&sd, 0, sizeof(sd));
244 sd.Length = sizeof(sd);
245 sd.Related = SSF_RELATED_INDEPENDENT;
246 sd.FgBg = SSF_FGBG_BACK;
247 sd.PgmName = EXECNAME;
248 if (pRes->krb5support)
249 {
250 StrNCat(params, " -k ", sizeof(params) - 1);
251 }
252 if (pRes->loglevel)
253 {
254 char level[2];
255 level[0] = pRes->loglevel + '0';
256 level[1] = 0;
257 StrNCat(params, " -d ", sizeof(params) - 1);
258 StrNCat(params, level, sizeof(params) - 1);
259 }
260 if (*pRes->logfile)
261 {
262 StrNCat(params, " -l ", sizeof(params) - 1);
263 StrNCat(params, pRes->logfile, sizeof(params) - 1);
264 }
265
266 log("params <%s>\n", params);
267 sd.PgmInputs = *params ? params : NULL;
268 sd.SessionType = SSF_TYPE_WINDOWABLEVIO;
269 rc = DosStartSession(&sd, &sid, &pid);
270 log("smbcd startsession pid %d sid %d rc %d\n", pid, sid, rc);
271 if (rc == ERROR_SMG_INVALID_CALL)
272 {
273 // ndfs started ndctl detached, so we have to use dosexecpgm
274 char failed[CCHMAXPATH + 1] = {0};
275 RESULTCODES res = {0};
276 UCHAR pszArgString[CCHMAXPATH+41] ; /* Argument string */
277 sprintf(pszArgString, "smbcd %s\0", params);
278 if (params!=NULL)
279 pszArgString[5] = '\0' ;
280 rc = DosExecPgm(failed, sizeof(failed), EXEC_BACKGROUND, pszArgString, NULL, &res, EXECNAME);
281 log("smbcd DosExecPgm codeTerminate %d codeResult %d rc %d\n", res.codeTerminate, res.codeResult, rc);
282 }
283 if (!rc)
284 {
285 DosSleep(500);
286 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
287 log("DosOpen2 rc %d\n", rc);
288 }
289 }
290 if (!rc)
291 {
292 if (ppipe)
293 {
294 *ppipe = pipe;
295 }
296 else
297 {
298 DosClose(pipe);
299 }
300 }
301 return rc;
302}
303
304
305void getfindinfo(Connection * pConn, FILEFINDBUF3 * stat, smbwrp_fileinfo * finfo)
306{
307 char * name = ph->fsphStrRChr(finfo->fname, '\\');
308 if (name)
309 {
310 name++;
311 }
312 else
313 {
314 name = finfo->fname;
315 }
316 if (!*name)
317 {
318 name = pConn->srv.share_name;
319 }
320 StrNCpy(stat->achName, name, CCHMAXPATHCOMP - 1);
321 stat->cbFile = finfo->size;
322 stat->cbFileAlloc = stat->cbFile;
323 stat->oNextEntryOffset = 0ul;
324 stat->cchName = StrLen(stat->achName);
325 stat->attrFile = (finfo->attr & 0x37);
326
327 ph->fsphUnixTimeToDosDate(finfo->mtime, &stat->fdateLastWrite, &stat->ftimeLastWrite);
328 ph->fsphUnixTimeToDosDate(finfo->ctime, &stat->fdateCreation, &stat->ftimeCreation);
329 ph->fsphUnixTimeToDosDate(finfo->atime, &stat->fdateLastAccess, &stat->ftimeLastAccess);
330}
331
332int getfindinfoL(Connection * pConn, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
333{
334 FILESTATUS3L stat = {0};
335 char * name = ph->fsphStrRChr(finfo->fname, '\\');
336 if (name)
337 {
338 name++;
339 }
340 else
341 {
342 name = finfo->fname;
343 }
344 if (!*name)
345 {
346 name = pConn->srv.share_name;
347 }
348 if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
349 {
350 return 0;
351 }
352
353 stat.cbFile = finfo->size;
354 stat.cbFileAlloc = stat.cbFile;
355 stat.attrFile = (finfo->attr & 0x37);
356
357 ph->fsphUnixTimeToDosDate(finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
358 ph->fsphUnixTimeToDosDate(finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
359 ph->fsphUnixTimeToDosDate(finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
360
361 ph->fsphAddFile32L(plist, &stat, name, StrLen(name), finfo, sizeof(*finfo), 0);
362 return 1;
363}
364
365
366/* accept parameters in form
367 * [filename][;name=filename]
368 */
369int initResource (Resource *pRes)
370{
371 int rc = NO_ERROR;
372 unsigned long t;
373 const unsigned char * q = NULL;
374 HPIPE pipe;
375
376 pRes->memlen = 1 << 18;
377 pRes->rootlevel = 0;
378 *pRes->logfile = 0;
379 pRes->loglevel = 0;
380 pRes->easupport = 1;
381 pRes->krb5support = 0;
382
383 t = 0, q = NULL;
384 rc = ph->fsphQueryStringProperty (pRes->properties, "WORKGROUP", &q, &t);
385 if (!rc && t && *q)
386 {
387 StrNCpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
388 pRes->rootlevel = 1;
389 }
390
391 t = 0, q = NULL;
392 rc = ph->fsphQueryStringProperty (pRes->properties, "SERVER", &q, &t);
393 if (!rc && t && *q)
394 {
395 StrNCpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
396 pRes->rootlevel = 2;
397 }
398
399 t = 0, q = NULL;
400 rc = ph->fsphQueryStringProperty (pRes->properties, "SHARE", &q, &t);
401 if (!rc && t && *q)
402 {
403 StrNCpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
404 pRes->rootlevel = 3;
405 }
406
407 t = 0, q = NULL;
408 rc = ph->fsphQueryStringProperty (pRes->properties, "USER", &q, &t);
409 if (!rc && t && *q)
410 {
411 StrNCpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
412 }
413
414 t = 0, q = NULL;
415 rc = ph->fsphQueryStringProperty (pRes->properties, "PASSWORD", &q, &t);
416 if (!rc && t && *q)
417 {
418 StrNCpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
419 }
420
421 t = 0, q = NULL;
422 rc = ph->fsphQueryStringProperty (pRes->properties, "MASTER", &q, &t);
423 if (!rc && t && *q)
424 {
425 StrNCpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
426 }
427
428 t = 0, q = NULL;
429 rc = ph->fsphQueryStringProperty (pRes->properties, "LOGFILE", &q, &t);
430 if (!rc && t && *q)
431 {
432 StrNCpy(pRes->logfile, q, sizeof(pRes->logfile) - 1);
433 }
434
435 t = 0;
436 rc = ph->fsphQueryUlongProperty (pRes->properties, "LOGLEVEL", &t);
437 if (!rc)
438 {
439 if (t > 9)
440 {
441 t = 9;
442 rc = ERROR_INVALID_PARAMETER;
443 }
444 pRes->loglevel = t;
445 }
446
447 t = 0;
448 rc = ph->fsphQueryUlongProperty (pRes->properties, "MASTERTYPE", &t);
449 if (!rc)
450 {
451 if (t > 1)
452 {
453 rc = ERROR_INVALID_PARAMETER;
454 }
455 else
456 {
457 pRes->srv.ifmastergroup = t;
458 }
459 }
460
461 t = 0;
462 rc = ph->fsphQueryUlongProperty (pRes->properties, "EASUPPORT", &t);
463 if (!rc)
464 {
465 if (t > 1)
466 {
467 rc = ERROR_INVALID_PARAMETER;
468 }
469 else
470 {
471 pRes->easupport = t;
472 }
473 }
474
475 t = 0;
476 rc = ph->fsphQueryUlongProperty (pRes->properties, "MEMLEN", &t);
477 if (!rc)
478 {
479 if (t <= (pRes->easupport ? 1 : 0) || t > 10)
480 {
481 rc = ERROR_INVALID_PARAMETER;
482 }
483 else
484 {
485 pRes->memlen = t * 65536;
486 }
487 }
488
489 t = 0;
490 rc = ph->fsphQueryUlongProperty (pRes->properties, "KRB5SUPPORT", &t);
491 if (!rc)
492 {
493 if (t > 1)
494 {
495 rc = ERROR_INVALID_PARAMETER;
496 }
497 else
498 {
499 pRes->krb5support = t;
500 }
501 }
502
503 return rc;
504}
505
506int checkconnection(Connection * pConn)
507{
508 int rc = NO_ERROR;
509 unsigned long action;
510 smb_request req = {0};
511 smb_response resp = {0};
512 char* mem;
513
514 if (!pConn)
515 {
516 return ERROR_INVALID_PARAMETER;
517 }
518 log("checkconnection pconnrc %d pipe %d\n", pConn->rc, pConn->pipe);
519 // YD this code need probably to be removed (reworked), since DosQueryNPHState,
520 // DosQueryNPipeInfo, DosPeekNPipe, DosResetBuffer, are all returning
521 // NO_ERROR even if the other pipe end is closed (smbcd crash).
522 //
523 // YD TODO probably checkconnection() call can be removed since we
524 // detect broken pipes inside _DosTransactNPipe
525 if (!pConn->rc)
526 {
527 unsigned long state = 0;
528 rc = DosQueryNPHState(pConn->pipe, &state);
529 log("DosQueryNPHstate(pConn->pipe) = %d (%08x)\n", pConn->rc, pConn->pipe, rc, state);
530 if (!rc)
531 {
532 return pConn->rc;
533 }
534 }
535 // there were error on pipe, reopen it and restore connection
536 if (pConn->pipe)
537 {
538 DosClose(pConn->pipe);
539 pConn->pipe = 0;
540 }
541 rc = openpipe(pConn->pRes, &pConn->pipe);
542 if (rc)
543 {
544 log("checkconnection openpipe %d\n", rc);
545 pConn->pipe = 0;
546 DosSleep(1000);
547 return ERROR_PIPE_NOT_CONNECTED;
548 }
549
550 // if we are reconnecting pipe because of a broken pipe, we
551 // need to save shared memory content to allow operation retry
552 mem = malloc( pConn->pRes->memlen);
553 if (mem)
554 memcpy( mem, pConn->mem, pConn->pRes->memlen);
555
556 // reinit connection
557 do {
558 req.request = SMBREQ_INIT;
559 req.param = (char *)0xFFFFFFFF;
560 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
561 if (pConn->rc || action < sizeof(resp) || resp.rc)
562 {
563 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
564 break;
565 }
566 pConn->clientpid = resp.value & 0xFFFF;
567 // client daemon pid changed
568 pConn->rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
569 if (pConn->rc)
570 {
571 rc = pConn->rc;
572 break;
573 }
574 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
575
576 req.request = SMBREQ_CONNECT;
577 req.param = pConn->mem;
578 req.paramlen = sizeof(pConn->srv);
579 req.length = req.paramlen;
580
581 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
582 if (pConn->rc || action < sizeof(resp) || resp.rc)
583 {
584 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
585 break;
586 }
587 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
588
589 rc = NO_ERROR;
590 } while (0);
591
592 // if we are reconnecting pipe because of a broken pipe, we
593 // need to restore shared memory content to allow operation retry
594 if (mem) {
595 memcpy( pConn->mem, mem, pConn->pRes->memlen);
596 free( mem);
597 }
598
599 if (pConn->rc && pConn->pipe)
600 {
601 DosClose(pConn->pipe);
602 pConn->pipe = 0;
603 }
604 return rc;
605}
606
607/*
608 * YD Since DosQueryNPHState,
609 * DosQueryNPipeInfo, DosPeekNPipe, DosResetBuffer, are all returning
610 * NO_ERROR even if the other pipe end is closed (smbcd crash),
611 * we can detect broken pipes only when writing/reading from the pipe.
612*/
613ULONG APIENTRY _DosTransactNPipe(Connection *pConn, PVOID pOutbuf, ULONG ulOutbufLength,
614 PVOID pInbuf, ULONG ulInbufLength, PULONG pulBytesRead)
615{
616 APIRET rc;
617
618 // try first
619 rc = DosTransactNPipe(pConn->pipe, pOutbuf, ulOutbufLength, pInbuf, ulInbufLength, pulBytesRead);
620 if (rc != ERROR_BROKEN_PIPE)
621 return rc;
622 // client daemon closed, force open connection again
623 pConn->rc = rc;
624 checkconnection( pConn);
625 // issue command again
626 rc = DosTransactNPipe(pConn->pipe, pOutbuf, ulOutbufLength, pInbuf, ulInbufLength, pulBytesRead);
627 return rc;
628}
629
630int iftestpath(char * path)
631{
632 char * p = path;
633 if (!path)
634 {
635 return 0;
636 }
637 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
638 {
639 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
640 {
641 return 1;
642 }
643 p++;
644 }
645 return 0;
646}
647
648int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
649{
650 int rootlevel;
651 int rc = NO_ERROR;
652 if (!pRes || !path || !result)
653 {
654 return ERROR_INVALID_PARAMETER;
655 }
656 // handle special case when someone wants to test support of LFN or smth similar
657 if (iftestpath(path))
658 {
659 StrCpy(result, "\\A.+,;=[].B");
660 return NO_ERROR;
661 }
662 rootlevel = pRes->rootlevel;
663 if (*path == '\\') path++;
664 if (rootlevel < 3)
665 {
666 char * p;
667 int newlevel = 0;
668 smbwrp_server * tmp = (smbwrp_server *)pConn->mem;
669 MemCpy(tmp, &pConn->srv, sizeof(pConn->srv));
670 if (rootlevel == 0)
671 {
672 p = ph->fsphStrChr(path, '\\');
673 if (!p)
674 {
675 p = path + StrLen(path);
676 }
677 if (StrLen(tmp->workgroup) != p - path
678 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
679 {
680 StrNCpy(tmp->workgroup, path, p - path);
681 tmp->workgroup[p - path] = 0;
682 newlevel = 1;
683 }
684 path = *p == '\\' ? p + 1 : p;
685 rootlevel = 1;
686 }
687 if (rootlevel == 1) // root path starts from server name
688 {
689 p = ph->fsphStrChr(path, '\\');
690 if (!p)
691 {
692 p = path + StrLen(path);
693 }
694 if (StrLen(tmp->server_name) != p - path
695 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
696 {
697 StrNCpy(tmp->server_name, path, p - path);
698 tmp->server_name[p - path] = 0;
699 newlevel = 1;
700 }
701 path = *p == '\\' ? p + 1 : p;
702 rootlevel = 2;
703 }
704 if (rootlevel == 2) // root path starts from share name
705 {
706 p = ph->fsphStrChr(path, '\\');
707 if (!p)
708 {
709 p = path + StrLen(path);
710 }
711 if (StrLen(tmp->share_name) != (p - path)
712 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
713 {
714 StrNCpy(tmp->share_name, path, p - path);
715 tmp->share_name[p - path] = 0;
716 newlevel = 1;
717 }
718 path = *p == '\\' ? p + 1 : p;
719 }
720 if (newlevel)
721 {
722 // reconnect to server here
723 unsigned long action;
724 smb_request req = {0};
725 smb_response resp = {0};
726
727 req.request = SMBREQ_DISCONNECT;
728 req.param = pConn->mem;
729 req.length = 0;
730 req.paramlen = 0;
731
732 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
733
734 req.request = SMBREQ_CONNECT;
735 req.param = pConn->mem;
736 req.length = pRes->memlen;
737 req.paramlen = sizeof(pConn->srv);
738
739 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
740 if (rc || action < sizeof(resp) || resp.rc)
741 {
742 APIRET rc2;
743 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
744 MemCpy(tmp, &pRes->srv, sizeof(pRes->srv));
745 rc2 = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
746 // TODO: what to do if the reconnect will fail ?
747 }
748 else
749 {
750 MemCpy(&pConn->srv, tmp, sizeof(pConn->srv));
751 }
752 }
753 }
754 StrCpy(result, "\\");
755 StrNCat(result, path, CCHMAXPATH);
756 return rc;
757}
758
759int APIENTRY NdpFreeResource (HRESOURCE resource)
760{
761 Resource *pRes = (Resource *)resource;
762 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
763 DosFreeMem(pRes);
764 log("NdpFreeResource %d\n", NO_ERROR);
765 return NO_ERROR;
766}
767
768
769int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
770{
771 int rc = NO_ERROR;
772 unsigned long objany = OBJ_ANY;
773 Resource *pRes = NULL;
774 /* since we support only 1 type of resources we do not need */
775 /* to check what the found type really is */
776 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE | objany);
777 if (rc == ERROR_INVALID_PARAMETER)
778 {
779 objany = 0;
780 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE);
781 }
782 if (!rc && pRes == NULL)
783 {
784 rc = ERROR_NOT_ENOUGH_MEMORY;
785 }
786 if (!rc)
787 {
788 MemSet(pRes, 0, sizeof(Resource));
789 pRes->properties = properties;
790 pRes->objany = objany;
791 rc = initResource (pRes);
792 if (rc == NO_ERROR)
793 {
794 *presource = (HRESOURCE)pRes;
795 }
796 else
797 {
798 NdpFreeResource((HRESOURCE)pRes);
799 }
800 }
801 log("NdpMountResource %d\n", rc);
802 return rc;
803}
804
805int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
806{
807 int rc;
808 Resource * pRes = (Resource *)resource;
809 unsigned long action;
810 smb_request req = {0};
811 smb_response resp = {0};
812 Connection *pConn = NULL;
813
814 log("NdpCreateConnection in\n");
815
816 rc = DosAllocMem((void **)&pConn, sizeof(Connection), PAG_COMMIT | PAG_READ | PAG_WRITE | pRes->objany);
817 if (!rc && pConn == NULL)
818 {
819 rc = ERROR_NOT_ENOUGH_MEMORY;
820 }
821 if (rc)
822 {
823 log("NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
824 return rc;
825 }
826 MemSet(pConn, 0, sizeof(Connection));
827 pConn->pRes = pRes;
828 pConn->file.fd = -1;
829
830 do {
831 log("NdpCreateConnection open pipe\n");
832 rc = openpipe(pRes, &pConn->pipe);
833 if (rc)
834 {
835 pConn->pipe = 0;
836 break;
837 }
838
839 log("NdpCreateConnection send INIT\n");
840 req.request = SMBREQ_INIT;
841 req.param = (char *)0xFFFFFFFF;
842 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
843 if (rc || action < sizeof(resp) || resp.rc)
844 {
845 return rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
846 }
847 pConn->clientpid = resp.value & 0xFFFF;
848
849 rc = DosAllocSharedMem((PPVOID)&pConn->mem, NULL, pRes->memlen, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | pRes->objany);
850 if (rc)
851 {
852 break;
853 }
854 rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
855 if (rc)
856 {
857 break;
858 }
859
860 log("NdpCreateConnection send CONNECT\n");
861 MemCpy(pConn->mem, &pRes->srv, sizeof(pRes->srv));
862 req.request = SMBREQ_CONNECT;
863 req.param = pConn->mem;
864 req.paramlen = sizeof(pConn->srv);
865 req.length = req.paramlen;
866
867 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
868 if (rc || action < sizeof(resp) || resp.rc)
869 {
870 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
871 }
872 else
873 {
874 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
875 }
876 } while (0);
877 if (rc)
878 {
879 if (pConn->mem)
880 {
881 DosFreeMem(pConn->mem);
882 }
883 if (pConn->pipe)
884 {
885 DosClose(pConn->pipe);
886 }
887 MemSet(pConn, 0, sizeof(*pConn));
888 DosFreeMem(pConn);
889 pConn = NULL;
890 }
891
892 *pconn = (HCONNECTION)pConn;
893 log("NdpCreateConnection %d %d\n", rc, resp.rc);
894 return rc;
895}
896
897
898int APIENTRY NdpFreeConnection (HCONNECTION conn)
899{
900 Connection *pConn = (Connection *)conn;
901 Resource *pRes = pConn->pRes;
902
903 log("NdpFreeConnection in\n");
904 if (pConn->mem)
905 {
906 smb_request req = {0};
907 smb_response resp = {0};
908 unsigned long action;
909 if (pConn->file.fd >= 0)
910 {
911 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
912 req.request = SMBREQ_CLOSE;
913 req.param = pConn->mem;
914 req.length = sizeof(pConn->file);
915 req.paramlen = sizeof(pConn->file);
916
917 _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
918 pConn->file.fd = -1;
919 }
920
921 req.request = SMBREQ_DISCONNECT;
922 req.param = pConn->mem;
923 req.length = 0;
924 req.paramlen = 0;
925
926 _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
927
928 DosFreeMem(pConn->mem);
929 DosClose(pConn->pipe);
930 MemSet(pConn, 0, sizeof(*pConn));
931 }
932
933 DosFreeMem(pConn);
934 log("NdpFreeConnection %d\n", NO_ERROR);
935 return NO_ERROR;
936}
937
938int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
939{
940 Resource *pRes = (Resource *)resource;
941 Resource *pRes2 = (Resource *)resource2;
942 int rc = ND_RSRC_DIFFERENT;
943
944 log("NdpRsrcCompare in\n");
945
946 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
947 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
948 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
949 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
950 {
951 // resources are equal
952 rc = ND_RSRC_EQUAL;
953 }
954
955 log("NdpRsrcCompare %d\n", rc);
956
957 return rc;
958}
959
960int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
961{
962 // do nothing
963 log("NdpRsrcUpdate %d\n", NO_ERROR);
964 return NO_ERROR;
965}
966
967int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
968{
969 Resource *pRes = (Resource *)resource;
970 int rc = NO_ERROR;
971 char s[4096];
972
973 log("NdpRsrcQueryInfo in\n");
974
975 switch (pRes->rootlevel)
976 {
977 case 0:
978 {
979 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
980 } break;
981 case 1:
982 {
983 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
984 } break;
985 case 2:
986 {
987 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.username);
988 } break;
989 default:
990 {
991 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s\\%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.share_name, pRes->srv.username);
992 } break;
993 }
994 *poutlen = StrLen(s) + 1;
995 if (*poutlen > insize)
996 {
997 rc = ERROR_BUFFER_OVERFLOW;
998 }
999 else
1000 {
1001 MemCpy(pdata, s, *poutlen);
1002 }
1003
1004 log("NdpRsrcQueryInfo %d\n", rc);
1005
1006 return rc;
1007}
1008
1009int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
1010{
1011 ULONG ulDummy = 0;
1012 /* just return the resource info string */
1013 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
1014}
1015
1016int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
1017{
1018 int rc = NO_ERROR, rc1;
1019
1020 Connection *pConn = 0;
1021 smb_request req = {0};
1022 smb_response resp = {0};
1023 unsigned long action = 0;
1024
1025 log("NdpRsrcQueryFSAllocate %08x\n", pfsa);
1026
1027 if (!pfsa)
1028 {
1029 return NO_ERROR;
1030 }
1031
1032
1033 rc = NdpCreateConnection (resource, (HCONNECTION *)&pConn);
1034 if (rc)
1035 {
1036 log("NdpCreateConnection failed rc=%d\n", rc);
1037 pfsa->cSectorUnit = 1;
1038 pfsa->cUnit = 123456;
1039 pfsa->cUnitAvail = 123456;
1040 pfsa->cbSector = 2048;
1041 return rc;
1042 }
1043
1044 MemSet(pConn->mem, 0, sizeof(FSALLOCATE));
1045 req.request = SMBREQ_DSKATTR;
1046 req.param = pConn->mem;
1047 req.paramlen = sizeof(FSALLOCATE);
1048 req.length = req.paramlen;
1049
1050 rc = DosTransactNPipe( pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1051 if (rc || action < sizeof(resp) || resp.rc)
1052 {
1053 pfsa->cSectorUnit = 1;
1054 pfsa->cUnit = 123456;
1055 pfsa->cUnitAvail = 123456;
1056 pfsa->cbSector = 2048;
1057 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1058 }
1059 else
1060 {
1061 FSALLOCATE * fsa = (FSALLOCATE *)pConn->mem;
1062 pfsa->cSectorUnit = fsa->cSectorUnit;
1063 pfsa->cUnit = fsa->cUnit;
1064 pfsa->cUnitAvail = fsa->cUnitAvail;
1065 pfsa->cbSector = fsa->cbSector;
1066 }
1067
1068 rc1 = NdpFreeConnection((HCONNECTION)pConn);
1069
1070 log("NdpRsrcQueryFSAllocate %d/%d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, resp.rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
1071 return rc;
1072}
1073
1074int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1075{
1076 Connection *pConn = (Connection *)conn;
1077 Resource *pRes = pConn->pRes;
1078 int rc = NO_ERROR, count = 0;
1079 unsigned long action;
1080 smb_request req = {0};
1081 smb_response resp = {0};
1082 char *mask = "*";
1083 char dir[CCHMAXPATH+1] = {0};
1084 char path[CCHMAXPATH+1] = {0};
1085 char fullname[CCHMAXPATH+1] = {0};
1086 smbwrp_fileinfo * data;
1087 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1088
1089 log("NdpFindStart in\n");
1090 do
1091 {
1092 rc = checkconnection(pConn);
1093 if (rc)
1094 {
1095 break;
1096 }
1097
1098 StrNCpy(dir, szPath, sizeof(dir) - 1);
1099 if (pel)
1100 {
1101 mask = pel->name;
1102 dir[StrLen(szPath) - pel->length] = 0;
1103 }
1104 action = StrLen(dir) - 1;
1105 if (dir[action] == '\\')
1106 {
1107 dir[action] = 0;
1108 }
1109 rc = pathparser(pRes, pConn, dir, path);
1110 if (rc)
1111 {
1112 break;
1113 }
1114 action = StrLen(path) - 1;
1115 if (path[action] != '\\')
1116 {
1117 StrNCat(path, "\\", sizeof(path) - 1);
1118 }
1119 StrCpy(dir, path);
1120 StrNCat(path, mask, sizeof(path) - 1);
1121
1122 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
1123 StrCpy(pConn->mem + sizeof(pConn->srv), path);
1124 req.request = SMBREQ_FILELIST;
1125 req.param = pConn->mem;
1126 req.paramlen = sizeof(pConn->srv) + CCHMAXPATH + 1;
1127 req.length = pRes->memlen;
1128 data = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->srv) + CCHMAXPATH + 1);
1129
1130 do {
1131 int i;
1132 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1133 if (pConn->rc || action < sizeof(resp)
1134 || (resp.rc && resp.rc != ERROR_MORE_DATA))
1135 {
1136 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1137 break;
1138 }
1139log("NdpFindStart %d %d %d\n", pConn->rc, resp.rc, resp.length / sizeof(smbwrp_fileinfo));
1140 if (ifL)
1141 {
1142 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1143 {
1144 smbwrp_fileinfo * finfo = data + i;
1145log("NdpFindStart found <%s> %d\n", finfo->fname, finfo->easize);
1146 StrCpy(fullname, dir);
1147 StrCat(fullname, finfo->fname);
1148 StrCpy(finfo->fname, fullname);
1149 count += getfindinfoL(pConn, plist, finfo, ulAttribute, mask);
1150 }
1151 }
1152 else
1153 {
1154 FILEFINDBUF3 buf = {0};
1155 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1156 {
1157 smbwrp_fileinfo * finfo = data + i;
1158 getfindinfo(pConn, &buf, finfo);
1159
1160 if (ph->fsphAttrMatch(ulAttribute, buf.attrFile)
1161 && ph->fsphWildMatch(mask, buf.achName, ND_IGNORE_CASE))
1162 {
1163 StrCpy(fullname, dir);
1164 StrCat(fullname, finfo->fname);
1165 StrCpy(finfo->fname, fullname);
1166 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1167 count++;
1168 }
1169 }
1170 }
1171 } while (resp.rc == ERROR_MORE_DATA);
1172 } while (0);
1173
1174 log("NdpFindStart <%s> (%s) cnt %d %d %d\n", szPath, path, count, rc, pConn->rc);
1175 return rc;
1176}
1177
1178int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
1179{
1180 Connection *pConn = (Connection *)conn;
1181 Resource *pRes = pConn->pRes;
1182 int rc = 0;
1183 unsigned long action;
1184 smb_request req = {0};
1185 smb_response resp = {0};
1186 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1187 char path[CCHMAXPATH+1] = {0};
1188
1189 log("NdpQueryInfo in <%s>\n", szPath);
1190
1191 do {
1192 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
1193 {
1194 rc = ERROR_FILE_NOT_FOUND;
1195 break;
1196 }
1197
1198 rc = checkconnection(pConn);
1199 if (rc)
1200 {
1201 break;
1202 }
1203
1204 rc = pathparser(pRes, pConn, szPath, path);
1205 switch (rc)
1206 {
1207 case NO_ERROR :
1208 case ERROR_FILE_NOT_FOUND:
1209 case ERROR_PATH_NOT_FOUND:
1210 case ERROR_ACCESS_DENIED:
1211 case ERROR_INVALID_PARAMETER:
1212 {
1213 break;
1214 }
1215 default :
1216 {
1217 rc = ERROR_PATH_NOT_FOUND;
1218 }
1219 }
1220 if (rc)
1221 {
1222 break;
1223 }
1224 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1225 req.request = SMBREQ_GETINFO;
1226 req.param = pConn->mem;
1227 req.paramlen = sizeof(*finfo);
1228 req.length = req.paramlen;
1229 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1230 if (pConn->rc || action < sizeof(resp) || resp.rc)
1231 {
1232 switch (resp.rc)
1233 {
1234 case NO_ERROR :
1235 case ERROR_FILE_NOT_FOUND:
1236 case ERROR_PATH_NOT_FOUND:
1237 case ERROR_ACCESS_DENIED:
1238 case ERROR_INVALID_PARAMETER:
1239 break;
1240 default :
1241 {
1242 resp.rc = ERROR_PATH_NOT_FOUND;
1243 }
1244 }
1245 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1246 }
1247 else
1248 {
1249 finfo->easize = -1;
1250 if (ifL)
1251 {
1252 getfindinfoL(pConn, plist, finfo, 0, NULL);
1253 }
1254 else
1255 {
1256 int trc;
1257 FILEFINDBUF3 buf = {0};
1258 getfindinfo(pConn, &buf, finfo);
1259 trc = ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1260 log("NdpQueryInfo got info <%s> attr %08x size %d namelen %d date %lu %lu. Plist 0x%08x rc = %d\n", buf.achName, buf.attrFile, buf.cbFile, buf.cchName, buf.fdateLastWrite, buf.ftimeLastWrite, plist, trc);
1261 }
1262 }
1263 if (rc == ERROR_FILE_NOT_FOUND)
1264 {
1265 // now try the upper path
1266 char * p = ph->fsphStrChr(finfo->fname, '\\');
1267 if (p && p > finfo->fname)
1268 {
1269 *p = 0;
1270 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1271 if (pConn->rc || action < sizeof(resp) || resp.rc)
1272 {
1273 rc = pConn->rc ? pConn->rc : (resp.rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER);
1274 }
1275 }
1276 }
1277 } while (0);
1278
1279 log("NdpQueryInfo <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1280 return rc;
1281}
1282
1283int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1284{
1285// log("NdpDeletePathInfo %d\n", 0);
1286 return NO_ERROR;
1287}
1288
1289int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1290{
1291 log("NdpRefresh <%s> %d\n", path, 0);
1292 return NO_ERROR;
1293}
1294
1295int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1296{
1297 // The plugin do not have to deallocate anything
1298 // because resource data did not contain any pointers
1299 // to plugins data.
1300 // Data stored by fsphSetResourceData will be
1301 // deallocated by NetDrive.
1302
1303 log("NdpDicardresourceData %d\n", 0);
1304 return NO_ERROR;
1305}
1306
1307int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1308{
1309 Connection *pConn = (Connection *)conn;
1310 Resource *pRes = pConn->pRes;
1311 int rc = 0;
1312 unsigned long action;
1313 smb_request req = {0};
1314 smb_response resp = {0};
1315 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1316 char path[CCHMAXPATH+1] = {0};
1317
1318 log("NdpSetPathInfo in\n");
1319 do {
1320 rc = checkconnection(pConn);
1321 if (rc)
1322 {
1323 break;
1324 }
1325
1326 rc = pathparser(pRes, pConn, szPathName, path);
1327 if (rc)
1328 {
1329 break;
1330 }
1331
1332 MemSet(finfo, 0, sizeof(*finfo));
1333
1334 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1335 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(finfo->mtime));
1336 if (ifL)
1337 {
1338 finfo->attr = pfi->stat.attrFile & 0x37;
1339 }
1340 else
1341 {
1342 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
1343 finfo->attr = stat->attrFile & 0x37;
1344 }
1345 req.request = SMBREQ_SETINFO;
1346 req.param = pConn->mem;
1347 req.paramlen = sizeof(*finfo);
1348 req.length = req.paramlen;
1349 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1350 if (pConn->rc || action < sizeof(resp) || resp.rc)
1351 {
1352 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1353 }
1354 } while (0);
1355 log("NdpSetPathInfo <%s> (%s) %d %d\n", szPathName, path, rc, pConn->rc);
1356 return rc;
1357}
1358
1359int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1360{
1361 int rc = 0;
1362 FEA * pfea;
1363 FEA * pfeadest;
1364 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1365
1366 size = pFEASrc->cbList;
1367 pfea = pFEASrc->list;
1368 pfeadest = pFEAList->list;
1369 dsize = pFEAList->cbList;
1370//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1371 while (done < size)
1372 {
1373 char * name = (char *)(pfea + 1);
1374 int insert = 1;
1375 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1376 {
1377 GEA * pgea = pGEAList->list;
1378 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1379 insert = 0;
1380 while (done < size)
1381 {
1382//log("comp <%s> <%s>\n", name, pgea->szName);
1383 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1384 {
1385 insert = 1;
1386 break;
1387 }
1388 done += pgea->cbName + 2;
1389 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1390 }
1391 }
1392 if (insert)
1393 {
1394 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1395 if (ddone <= dsize)
1396 {
1397 pfeadest->cbName = pfea->cbName;
1398 pfeadest->cbValue = pfea->cbValue;
1399 pfeadest->fEA = 0;
1400 StrCpy((char *)(pfeadest + 1), name);
1401 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1402 pfeadest = (FEA *)((char *)pFEAList + ddone);
1403 }
1404 }
1405 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1406//log("buuildfea <%s> insert=%d pfea->cbName=%d pfea->cbValue=%d srcdone=%d destdone=%d pfeadest=%08x pfea=%08x\n", name, insert, pfea->cbName, pfea->cbValue, done, ddone, pfeadest, pfea);
1407 pfea = (FEA *)((char *)pFEASrc + done);
1408 }
1409 pFEAList->cbList = ddone;
1410 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1411 {
1412 rc = ERROR_BUFFER_OVERFLOW;
1413 }
1414 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1415 return rc;
1416}
1417
1418int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1419{
1420 Connection *pConn = (Connection *)conn;
1421 Resource *pRes = pConn->pRes;
1422 int rc = 0;
1423 unsigned long action;
1424 smb_request req = {0};
1425 smb_response resp = {0};
1426 char * path = NULL;
1427 FEALIST * pFEASrc;
1428 NDDATABUF fdata = {0};
1429 smbwrp_fileinfo *finfo;
1430
1431 if (!pfi || !pfi->pszName || !pFEAList)
1432 {
1433 return ERROR_EAS_NOT_SUPPORTED;
1434 }
1435 if (!pRes->easupport)
1436 {
1437 return ERROR_EAS_NOT_SUPPORTED;
1438 }
1439
1440 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1441 if (rc || !fdata.ulSize || !fdata.pData)
1442 {
1443 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1444 return ERROR_EAS_NOT_SUPPORTED;
1445 }
1446 finfo = (smbwrp_fileinfo *)fdata.pData;
1447 path = finfo->fname;
1448
1449 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1450 do {
1451 rc = checkconnection(pConn);
1452 if (rc)
1453 {
1454 break;
1455 }
1456
1457 StrNCpy(pConn->mem, path, CCHMAXPATH);
1458 req.request = SMBREQ_LISTEA;
1459 req.param = pConn->mem;
1460 req.paramlen = CCHMAXPATH + 1;
1461 req.length = pRes->memlen - req.paramlen;
1462 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
1463 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1464 if (pConn->rc || action < sizeof(resp) || resp.rc)
1465 {
1466 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1467 switch (rc)
1468 {
1469 case ERROR_FILE_NOT_FOUND :
1470 case ERROR_PATH_NOT_FOUND :
1471 {
1472 pFEAList->cbList = sizeof(pFEAList->cbList);
1473 rc = NO_ERROR;
1474 } break;
1475 case ERROR_BUFFER_OVERFLOW :
1476 {
1477 pFEAList->cbList = pFEASrc->cbList;
1478 } break;
1479 default :
1480 {
1481 rc = ERROR_EAS_NOT_SUPPORTED;
1482 }
1483 }
1484 }
1485 else
1486 {
1487 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1488 }
1489 } while (0);
1490 log("NdpEAQuery <%s> %d %d %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList, pConn->rc, resp.rc);
1491 return rc;
1492}
1493
1494int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1495{
1496 Connection *pConn = (Connection *)conn;
1497 Resource *pRes = pConn->pRes;
1498 int rc = 0;
1499 smb_request req = {0};
1500 smb_response resp = {0};
1501 char * path;
1502 unsigned long action;
1503 NDDATABUF fdata = {0};
1504 smbwrp_fileinfo *finfo;
1505
1506 log("NdpEASet in\n");
1507
1508 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1509 {
1510 return ERROR_EAS_NOT_SUPPORTED;
1511 }
1512 if (!pRes->easupport)
1513 {
1514 return ERROR_EAS_NOT_SUPPORTED;
1515 }
1516
1517 if (pFEAList->cbList > pRes->memlen)
1518 {
1519 return ERROR_NOT_ENOUGH_MEMORY;
1520 }
1521
1522 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1523 if (rc || !fdata.ulSize || !fdata.pData)
1524 {
1525 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1526 return ERROR_EAS_NOT_SUPPORTED;
1527 }
1528 finfo = (smbwrp_fileinfo *)fdata.pData;
1529 path = finfo->fname;
1530
1531 do {
1532 rc = checkconnection(pConn);
1533 if (rc)
1534 {
1535 break;
1536 }
1537
1538 StrNCpy(pConn->mem, path, CCHMAXPATH);
1539 MemCpy(pConn->mem + CCHMAXPATH + 1, pFEAList, pFEAList->cbList);
1540 req.request = SMBREQ_SETEA;
1541 req.param = pConn->mem;
1542 req.paramlen = pFEAList->cbList + CCHMAXPATH + 1;
1543 req.length = req.paramlen;
1544 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1545 if (pConn->rc || action < sizeof(resp) || resp.rc)
1546 {
1547 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1548 }
1549 } while (0);
1550 log("NdpEASet %d\n", rc);
1551 return rc;
1552}
1553
1554int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1555{
1556 Connection *pConn = (Connection *)conn;
1557 Resource *pRes = pConn->pRes;
1558 int rc = 0;
1559 unsigned long action;
1560 smb_request req = {0};
1561 smb_response resp = {0};
1562 char * path = NULL;
1563 FEALIST * pfealist;
1564 NDDATABUF fdata = {0};
1565 smbwrp_fileinfo *finfo;
1566 int easize;
1567
1568 if (!pfi || !pulEASize)
1569 {
1570 return ERROR_EAS_NOT_SUPPORTED;
1571 }
1572 if (!pRes->easupport)
1573 {
1574 return ERROR_EAS_NOT_SUPPORTED;
1575 }
1576
1577 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1578 if (rc || !fdata.ulSize || !fdata.pData)
1579 {
1580 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1581 return ERROR_EAS_NOT_SUPPORTED;
1582 }
1583 finfo = (smbwrp_fileinfo *)fdata.pData;
1584 easize = finfo->easize;
1585 finfo->easize = -1;
1586 path = finfo->fname;
1587 if (easize >= 0)
1588 {
1589 *pulEASize = easize;
1590 log("NdpEASize <%s> cached %d\n", path, easize);
1591 return NO_ERROR;
1592 }
1593
1594 log("NdpEASize in <%s> \n", path);
1595 do {
1596 rc = checkconnection(pConn);
1597 if (rc)
1598 {
1599 break;
1600 }
1601
1602 StrNCpy(pConn->mem, path, CCHMAXPATH);
1603 req.request = SMBREQ_LISTEA;
1604 req.param = pConn->mem;
1605 req.paramlen = CCHMAXPATH + 1;
1606 req.length = pRes->memlen - req.paramlen;
1607 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
1608 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1609 if (pConn->rc || action < sizeof(resp) || resp.rc)
1610 {
1611 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1612 switch (rc)
1613 {
1614 case ERROR_FILE_NOT_FOUND :
1615 case ERROR_PATH_NOT_FOUND :
1616 {
1617 pfealist->cbList = sizeof(pfealist->cbList);
1618 } /* Fall through */
1619 case ERROR_BUFFER_OVERFLOW :
1620 {
1621 rc = NO_ERROR;
1622 } break;
1623 default :
1624 {
1625 rc = ERROR_EAS_NOT_SUPPORTED;
1626 }
1627 }
1628 }
1629 *pulEASize = pfealist->cbList;
1630 } while (0);
1631 log("NdpEASize <%s> %d %d %d %d\n", pfi->pszName, *pulEASize, rc, pConn->rc, resp.rc);
1632 return rc;
1633}
1634
1635int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1636{
1637 Connection *pConn = (Connection *)conn;
1638 Resource *pRes = pConn->pRes;
1639 smb_request req = {0};
1640 smb_response resp = {0};
1641 int rc = 0;
1642 unsigned long action;
1643 char path[CCHMAXPATH+1] = {0};
1644
1645 log("NdpSetCurrentDir in\n");
1646 do {
1647 rc = checkconnection(pConn);
1648 if (rc)
1649 {
1650 break;
1651 }
1652
1653 rc = pathparser(pRes, pConn, szPath, path);
1654 if (rc)
1655 {
1656 break;
1657 }
1658
1659 StrNCpy(pConn->mem, path, CCHMAXPATH);
1660 req.request = SMBREQ_CHDIR;
1661 req.param = pConn->mem;
1662 req.paramlen = CCHMAXPATH + 1;
1663 req.length = req.paramlen;
1664 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1665 if (pConn->rc || action < sizeof(resp) || resp.rc)
1666 {
1667 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1668 }
1669 } while (0);
1670 log("NdpSetCurrentDir <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1671 return rc;
1672}
1673
1674int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1675{
1676 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1677 return ERROR_CANNOT_COPY;
1678}
1679
1680int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1681{
1682 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1683 return ERROR_CANNOT_COPY;
1684}
1685
1686int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1687{
1688 Connection *pConn = (Connection *)conn;
1689 Resource *pRes = pConn->pRes;
1690 smb_request req = {0};
1691 smb_response resp = {0};
1692 int rc = 0;
1693 unsigned long action;
1694 char path[CCHMAXPATH+1] = {0};
1695
1696 log("NdpForceDelete in\n");
1697 do {
1698 rc = checkconnection(pConn);
1699 if (rc)
1700 {
1701 break;
1702 }
1703
1704 rc = pathparser(pRes, pConn, szFile, path);
1705 if (rc)
1706 {
1707 break;
1708 }
1709
1710 StrNCpy(pConn->mem, path, CCHMAXPATH);
1711 req.request = SMBREQ_UNLINK;
1712 req.param = pConn->mem;
1713 req.paramlen = CCHMAXPATH + 1;
1714 req.length = req.paramlen;
1715 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1716 if (pConn->rc || action < sizeof(resp) || resp.rc)
1717 {
1718 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1719 }
1720 } while (0);
1721 log("NdpForceDelete <%s> (%s) %d %d\n", szFile, path, rc, pConn->rc);
1722 return rc;
1723}
1724
1725int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1726{
1727 Connection *pConn = (Connection *)conn;
1728 Resource *pRes = pConn->pRes;
1729 smb_request req = {0};
1730 smb_response resp = {0};
1731 int rc = 0;
1732 unsigned long action;
1733 char path[CCHMAXPATH+1] = {0};
1734
1735 log("NdpCreateDir in\n");
1736 do {
1737 rc = checkconnection(pConn);
1738 if (rc)
1739 {
1740 break;
1741 }
1742
1743 rc = pathparser(pRes, pConn, szDirName, path);
1744 if (rc)
1745 {
1746 break;
1747 }
1748
1749 StrNCpy(pConn->mem, path, CCHMAXPATH);
1750 req.request = SMBREQ_MKDIR;
1751 req.param = pConn->mem;
1752 req.paramlen = CCHMAXPATH + 1;
1753 req.length = req.paramlen;
1754 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1755 if (pConn->rc || action < sizeof(resp) || resp.rc)
1756 {
1757 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1758 }
1759 } while (0);
1760 log("NdpCreateDir <%s> (%s) %d %d\n", szDirName, path, rc, pConn->rc);
1761 return rc;
1762}
1763
1764int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1765{
1766 Connection *pConn = (Connection *)conn;
1767 Resource *pRes = pConn->pRes;
1768 smb_request req = {0};
1769 smb_response resp = {0};
1770 int rc = 0;
1771 unsigned long action;
1772 char path[CCHMAXPATH+1] = {0};
1773
1774 log("NdpDeleteDir in\n");
1775 do {
1776 rc = checkconnection(pConn);
1777 if (rc)
1778 {
1779 break;
1780 }
1781
1782 rc = pathparser(pRes, pConn, szDir, path);
1783 if (rc)
1784 {
1785 break;
1786 }
1787
1788 StrNCpy(pConn->mem, path, CCHMAXPATH);
1789 req.request = SMBREQ_RMDIR;
1790 req.param = pConn->mem;
1791 req.paramlen = CCHMAXPATH + 1;
1792 req.length = req.paramlen;
1793 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1794 if (pConn->rc || action < sizeof(resp) || resp.rc)
1795 {
1796 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1797 }
1798 } while (0);
1799 log("NdpDeleteDir <%s> (%s) %d %d\n", szDir, path, rc, pConn->rc);
1800 return rc;
1801}
1802
1803int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1804{
1805 Connection *pConn = (Connection *)conn;
1806 Resource *pRes = pConn->pRes;
1807 smb_request req = {0};
1808 smb_response resp = {0};
1809 int rc = 0;
1810 unsigned long action;
1811 char src[CCHMAXPATH+1] = {0};
1812 int l1, l2;
1813 char * p = szDst;
1814
1815 log("NdpMove in\n");
1816 do
1817 {
1818 rc = checkconnection(pConn);
1819 if (rc)
1820 {
1821 break;
1822 }
1823
1824 rc = pathparser(pRes, pConn, szSrc, src);
1825 if (rc)
1826 {
1827 break;
1828 }
1829 l1 = StrLen(szSrc);
1830 l2 = StrLen(src);
1831 if (l1 > l2)
1832 {
1833 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1834 {
1835 // the file moved accross different shares or servers or workgroups
1836 rc = ERROR_WRITE_PROTECT;
1837 break;
1838 }
1839 p = szDst + l1 - l2 + 1;
1840 }
1841 StrNCpy(pConn->mem, src, CCHMAXPATH);
1842 pConn->mem[CCHMAXPATH + 1] = '\\';
1843 StrNCpy(pConn->mem + CCHMAXPATH + 2, p, CCHMAXPATH - 1);
1844 req.request = SMBREQ_RENAME;
1845 req.param = pConn->mem;
1846 req.paramlen = 2 * (CCHMAXPATH + 1);
1847 req.length = req.paramlen;
1848 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1849 if (pConn->rc || action < sizeof(resp) || resp.rc)
1850 {
1851 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1852 }
1853 } while (0);
1854 log("NdpMove <%s> -> <%s> (%s) %d %d\n", szSrc, szDst, src, rc, pConn->rc);
1855
1856 return rc;
1857}
1858
1859int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1860{
1861 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1862 return ERROR_WRITE_PROTECT;
1863}
1864
1865
1866int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1867{
1868 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1869}
1870
1871int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1872{
1873 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1874}
1875
1876int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1877{
1878 Resource *pRes = pConn->pRes;
1879 smb_request req = {0};
1880 smb_response resp = {0};
1881 unsigned long action;
1882 int rc = 0;
1883 char path[CCHMAXPATH+1] = {0};
1884
1885 log("smbopen in %d\n", pConn->file.fd);
1886 do {
1887 if (pConn->file.fd > 0)
1888 {
1889 rc = ERROR_TOO_MANY_OPEN_FILES;
1890 break;
1891 }
1892
1893 rc = checkconnection(pConn);
1894 if (rc)
1895 {
1896 break;
1897 }
1898
1899 rc = pathparser(pRes, pConn, szFileName, path);
1900 if (rc)
1901 {
1902 break;
1903 }
1904
1905 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1906 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1907 flags |= O_BINARY;
1908 switch (ulOpenMode & 3)
1909 {
1910 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1911 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1912 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1913 default : flags |= O_RDWR;
1914 }
1915 pConn->file.openmode = flags;
1916 pConn->file.openattr = ulAttribute & 0x37;
1917 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1918 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
1919 req.request = SMBREQ_OPEN;
1920 req.param = pConn->mem;
1921 req.paramlen = sizeof(pConn->file);
1922 req.length = req.paramlen;
1923 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1924 if (pConn->rc || action < sizeof(resp) || resp.rc)
1925 {
1926 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1927 }
1928 else
1929 {
1930 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
1931 }
1932 } while (0);
1933 log("smbopen <%s> (%s) %08x %08x %08x %d %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->rc, pConn->file.fd);
1934 if (!rc && pFEAList)
1935 {
1936 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1937 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1938 }
1939
1940 return rc;
1941}
1942
1943int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1944{
1945 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1946}
1947
1948int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1949{
1950 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1951}
1952
1953int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1954{
1955// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1956 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1957}
1958
1959int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1960{
1961 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1962}
1963
1964int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1965{
1966 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1967 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1968}
1969
1970int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1971{
1972 Connection *pConn = (Connection *)conn;
1973 Resource *pRes = pConn->pRes;
1974 int rc = 0;
1975 unsigned long action;
1976 smb_request req = {0};
1977 smb_response resp = {0};
1978 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1979 char path[CCHMAXPATH+1] = {0};
1980
1981 log("NdpSetFileAttribute in\n");
1982 do {
1983 rc = checkconnection(pConn);
1984 if (rc)
1985 {
1986 break;
1987 }
1988
1989 rc = pathparser(pRes, pConn, szFileName, path);
1990 if (rc)
1991 {
1992 break;
1993 }
1994
1995 MemSet(finfo, 0, sizeof(*finfo));
1996
1997 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1998 finfo->attr = usAttr & 0x37;
1999 req.request = SMBREQ_SETINFO;
2000 req.param = pConn->mem;
2001 req.paramlen = sizeof(*finfo);
2002 req.length = req.paramlen;
2003 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2004 if (pConn->rc || action < sizeof(resp) || resp.rc)
2005 {
2006 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2007 }
2008 } while (0);
2009 log("NdpSetFileAttribute <%s> (%s) %04x %d %d\n", szFileName, path, usAttr, rc, pConn->rc);
2010 return rc;
2011}
2012
2013int APIENTRY NdpFlush (HRESOURCE resource)
2014{
2015 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
2016 return ERROR_NOT_SUPPORTED;
2017}
2018
2019int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
2020{
2021 log("NdpIOCTL <%s> %d %d\n", path, function, ERROR_NOT_SUPPORTED);
2022 return ERROR_NOT_SUPPORTED;
2023}
2024
2025int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
2026{
2027 Connection *pConn = (Connection *)conn;
2028 Resource *pRes = pConn->pRes;
2029 int rc = 0;
2030 unsigned long action;
2031 smb_request req = {0};
2032 smb_response resp = {0};
2033 FILEFINDBUF3 buf;
2034 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->file));
2035
2036 log("NdpFileQueryInfo in\n");
2037 do {
2038 if (pConn->file.fd < 0 || !*pConn->file.fname)
2039 {
2040 rc = ERROR_INVALID_HANDLE;
2041 break;
2042 }
2043 if (pConn->rc)
2044 {
2045 rc = ERROR_PIPE_NOT_CONNECTED;
2046 break;
2047 }
2048
2049 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2050 StrNCpy(finfo->fname, pConn->file.fname, sizeof(finfo->fname) - 1);
2051 req.request = SMBREQ_FGETINFO;
2052 req.param = pConn->mem;
2053 req.paramlen = sizeof(pConn->file);
2054 req.length = req.paramlen + sizeof(*finfo);
2055 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2056 if (pConn->rc || action < sizeof(resp) || resp.rc)
2057 {
2058 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2059 }
2060 else
2061 {
2062 finfo->easize = -1;
2063 if (ifL)
2064 {
2065 getfindinfoL(pConn, plist, finfo, 0, NULL);
2066 }
2067 else
2068 {
2069 getfindinfo(pConn, &buf, finfo);
2070 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
2071 }
2072 }
2073 } while (0);
2074 log("NdpFileQueryInfo <%s> %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc, pConn->rc);
2075
2076 return rc;
2077}
2078
2079int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
2080{
2081 Connection *pConn = (Connection *)conn;
2082 Resource *pRes = pConn->pRes;
2083 int rc = 0;
2084 unsigned long action;
2085 smb_request req = {0};
2086 smb_response resp = {0};
2087 FEALIST * pFEASrc;
2088
2089 if (!pFEAList)
2090 {
2091 return ERROR_EAS_NOT_SUPPORTED;
2092 }
2093 if (!pRes->easupport)
2094 {
2095 return ERROR_EAS_NOT_SUPPORTED;
2096 }
2097
2098 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
2099 do {
2100 if (pConn->file.fd < 0)
2101 {
2102 rc = ERROR_INVALID_HANDLE;
2103 break;
2104 }
2105 if (pConn->rc)
2106 {
2107 rc = ERROR_PIPE_NOT_CONNECTED;
2108 break;
2109 }
2110
2111 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2112 req.request = SMBREQ_FLISTEA;
2113 req.param = pConn->mem;
2114 req.paramlen = sizeof(pConn->file);
2115 req.length = pRes->memlen - req.paramlen;
2116 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
2117 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2118 if (pConn->rc || action < sizeof(resp) || resp.rc)
2119 {
2120 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2121 switch (rc)
2122 {
2123 case ERROR_FILE_NOT_FOUND :
2124 case ERROR_PATH_NOT_FOUND :
2125 {
2126 pFEAList->cbList = sizeof(pFEAList->cbList);
2127 rc = NO_ERROR;
2128 } break;
2129 case ERROR_BUFFER_OVERFLOW :
2130 {
2131 pFEAList->cbList = pFEASrc->cbList;
2132 } break;
2133 default :
2134 {
2135 rc = ERROR_EAS_NOT_SUPPORTED;
2136 }
2137 }
2138 }
2139 else
2140 {
2141 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
2142 }
2143 } while (0);
2144 log("NdpFileEAQuery out <%s>/%d pFEASrc->cbList=%d pFEAList->cbList=%d rc=%d %d %d\n", pConn->file.fname, pConn->file.fd, pFEASrc->cbList, pFEAList->cbList, rc, pConn->rc, resp.rc);
2145 return rc;
2146}
2147
2148int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
2149{
2150 Connection *pConn = (Connection *)conn;
2151 Resource *pRes = pConn->pRes;
2152 int rc = 0;
2153 smb_request req = {0};
2154 smb_response resp = {0};
2155 unsigned long action;
2156
2157 log("NdpFileEASet in\n");
2158
2159 if (!pFEAList || pFEAList->cbList <= sizeof(long))
2160 {
2161 return ERROR_EAS_NOT_SUPPORTED;
2162 }
2163 if (!pRes->easupport)
2164 {
2165 return ERROR_EAS_NOT_SUPPORTED;
2166 }
2167 if (pFEAList->cbList > pRes->memlen)
2168 {
2169 return ERROR_NOT_ENOUGH_MEMORY;
2170 }
2171
2172 do {
2173 if (pConn->file.fd < 0)
2174 {
2175 rc = ERROR_INVALID_HANDLE;
2176 break;
2177 }
2178 if (pConn->rc)
2179 {
2180 rc = ERROR_PIPE_NOT_CONNECTED;
2181 break;
2182 }
2183
2184 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2185 MemCpy(pConn->mem + sizeof(pConn->file), pFEAList, pFEAList->cbList);
2186 req.request = SMBREQ_FSETEA;
2187 req.param = pConn->mem;
2188 req.paramlen = pFEAList->cbList + sizeof(pConn->file);
2189 req.length = req.paramlen;
2190
2191 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2192 if (pConn->rc || action < sizeof(resp) || resp.rc)
2193 {
2194 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2195 }
2196 } while (0);
2197 log("NdpFileEASet %d\n", rc);
2198 return rc;
2199}
2200
2201int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
2202{
2203 Connection *pConn = (Connection *)conn;
2204 Resource *pRes = pConn->pRes;
2205 int rc = 0;
2206 unsigned long action;
2207 smb_request req = {0};
2208 smb_response resp = {0};
2209 char path[CCHMAXPATH+1] = {0};
2210 FEALIST * pfealist;
2211
2212 if (!pulEASize)
2213 {
2214 return ERROR_EAS_NOT_SUPPORTED;
2215 }
2216 if (!pRes->easupport)
2217 {
2218 return ERROR_EAS_NOT_SUPPORTED;
2219 }
2220
2221 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
2222 do {
2223 if (pConn->file.fd < 0)
2224 {
2225 rc = ERROR_INVALID_HANDLE;
2226 break;
2227 }
2228 if (pConn->rc)
2229 {
2230 rc = ERROR_PIPE_NOT_CONNECTED;
2231 break;
2232 }
2233
2234 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2235 req.request = SMBREQ_FLISTEA;
2236 req.param = pConn->mem;
2237 req.paramlen = sizeof(pConn->file);
2238 req.length = pRes->memlen - req.paramlen;
2239 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
2240 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2241 if (pConn->rc || action < sizeof(resp) || resp.rc)
2242 {
2243 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2244 switch (rc)
2245 {
2246 case ERROR_FILE_NOT_FOUND :
2247 case ERROR_PATH_NOT_FOUND :
2248 {
2249 pfealist->cbList = sizeof(pfealist->cbList);
2250 } /* Fall through */
2251 case ERROR_BUFFER_OVERFLOW :
2252 {
2253 rc = NO_ERROR;
2254 } break;
2255 default :
2256 {
2257 rc = ERROR_EAS_NOT_SUPPORTED;
2258 }
2259 }
2260 }
2261 *pulEASize = pfealist->cbList;
2262 } while (0);
2263 log("NdpFileEASize %d %d %d %d\n", *pulEASize, rc, pConn->rc, resp.rc);
2264 return rc;
2265}
2266
2267int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2268{
2269 Connection *pConn = (Connection *)conn;
2270 Resource *pRes = pConn->pRes;
2271 int rc = 0;
2272 unsigned long action, attrFile;
2273 smb_request req = {0};
2274 smb_response resp = {0};
2275 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2276
2277 log("NdpFileSetInfo in\n");
2278 do {
2279 if (pConn->file.fd < 0 || !*pConn->file.fname)
2280 {
2281 rc = ERROR_INVALID_HANDLE;
2282 break;
2283 }
2284 if (pConn->rc)
2285 {
2286 rc = ERROR_PIPE_NOT_CONNECTED;
2287 break;
2288 }
2289 if (ifL)
2290 {
2291 attrFile = pfi->stat.attrFile;
2292 }
2293 else
2294 {
2295 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
2296 attrFile = stat->attrFile;
2297 }
2298 // deferred setinfo - on closing the file
2299 pConn->file.openattr = attrFile;
2300 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(pConn->file.mtime));
2301 } while (0);
2302 log("NdpFileSetInfo <%s> %08x %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc, pConn->rc);
2303 return NO_ERROR;
2304}
2305
2306int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2307{
2308 Connection *pConn = (Connection *)conn;
2309 Resource *pRes = pConn->pRes;
2310 int rc = 0;
2311 unsigned long action;
2312 smb_request req = {0};
2313 smb_response resp = {0};
2314
2315 log("NdpFileSetFilePtrl in\n");
2316 do {
2317 if (pConn->file.fd < 0)
2318 {
2319 rc = ERROR_INVALID_HANDLE;
2320 break;
2321 }
2322 if (pConn->rc)
2323 {
2324 rc = ERROR_PIPE_NOT_CONNECTED;
2325 break;
2326 }
2327
2328 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2329 *(unsigned long *)(pConn->mem + sizeof(pConn->file)) = ulMethod;
2330 *(long long *)(pConn->mem + sizeof(pConn->file) + sizeof(long)) = llOffset;
2331 req.request = SMBREQ_LSEEK;
2332 req.param = pConn->mem;
2333 req.paramlen = sizeof(pConn->file) + sizeof(long) + sizeof(long long);
2334 req.length = req.paramlen;
2335 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2336 if (pConn->rc || action < sizeof(resp) || resp.rc)
2337 {
2338 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2339 }
2340 else
2341 {
2342 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2343 *pllActual = pConn->file.offset;
2344 }
2345 } while (0);
2346 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc, pConn->rc);
2347
2348 return rc;
2349}
2350
2351int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2352{
2353 LONGLONG llActual;
2354 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2355 *pulActual = llActual & 0xFFFFFFFF;
2356 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2357 return rc;
2358}
2359
2360int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2361{
2362 Connection *pConn = (Connection *)conn;
2363 Resource *pRes = pConn->pRes;
2364 int rc = 0;
2365 unsigned long action;
2366 smb_request req = {0};
2367 smb_response resp = {0};
2368
2369 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2370
2371 do {
2372 if (pConn->file.fd < 0)
2373 {
2374 rc = ERROR_INVALID_HANDLE;
2375 break;
2376 }
2377 if (pConn->rc)
2378 {
2379 rc = ERROR_PIPE_NOT_CONNECTED;
2380 break;
2381 }
2382
2383 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2384 req.request = SMBREQ_CLOSE;
2385 req.param = pConn->mem;
2386 req.length = pRes->memlen;
2387 req.paramlen = sizeof(pConn->file);
2388 req.length = req.paramlen;
2389 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2390 if (pConn->rc || action < sizeof(resp) || resp.rc)
2391 {
2392 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2393 }
2394 else
2395 {
2396 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2397 }
2398 } while (0);
2399 log("NdpFileClose %d %d %d\n", pConn->file.fd, rc, pConn->rc);
2400 pConn->file.fd = -1;
2401 return rc;
2402}
2403
2404int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2405{
2406 log("NdpFileCommit %d\n", NO_ERROR);
2407 return NO_ERROR;
2408}
2409
2410
2411int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2412{
2413 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2414 log("NdpFileNewSize %ld %d\n", ulLen, rc);
2415 return rc;
2416}
2417
2418int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2419{
2420 Connection *pConn = (Connection *)conn;
2421 Resource *pRes = pConn->pRes;
2422 int rc = 0;
2423 unsigned long action;
2424 smb_request req = {0};
2425 smb_response resp = {0};
2426
2427 log("NdpFileNewSizeL in\n");
2428 do {
2429 if (pConn->file.fd < 0)
2430 {
2431 rc = ERROR_INVALID_HANDLE;
2432 break;
2433 }
2434 if (pConn->rc)
2435 {
2436 rc = ERROR_PIPE_NOT_CONNECTED;
2437 break;
2438 }
2439
2440 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2441 *(long long *)(pConn->mem + sizeof(pConn->file)) = llLen;
2442
2443 req.request = SMBREQ_NEWSIZE;
2444 req.param = pConn->mem;
2445 req.paramlen = sizeof(pConn->file) + sizeof(long long);
2446 req.length = req.paramlen;
2447
2448 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2449 if (pConn->rc || action < sizeof(resp) || resp.rc)
2450 {
2451 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2452 }
2453 else
2454 {
2455 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2456 }
2457 } while (0);
2458 log("NdpFileNewSizeL <%s> %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc, pConn->rc);
2459 return rc;
2460}
2461
2462int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2463{
2464 Connection *pConn = (Connection *)conn;
2465 Resource *pRes = pConn->pRes;
2466 int rc = 0;
2467 unsigned long done = 0;
2468 unsigned long onedone;
2469 unsigned long action;
2470 smb_request req = {0};
2471 smb_response resp = {0};
2472
2473 log("NdpFileRead in\n");
2474// log("NdpFileRead <%s> %lu\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead);
2475
2476 do {
2477 if (pConn->file.fd < 0)
2478 {
2479 rc = ERROR_INVALID_HANDLE;
2480 break;
2481 }
2482 if (pConn->rc)
2483 {
2484 rc = ERROR_PIPE_NOT_CONNECTED;
2485 break;
2486 }
2487
2488 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2489 req.request = SMBREQ_READ;
2490 req.param = pConn->mem;
2491 req.paramlen = sizeof(pConn->file);
2492
2493 while (done < ulRead)
2494 {
2495 req.length = req.paramlen + (pRes->memlen - req.paramlen < (ulRead - done) ? pRes->memlen - req.paramlen : (ulRead - done));
2496
2497 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2498 if (pConn->rc || action < sizeof(resp) || resp.rc)
2499 {
2500 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2501 break;
2502 }
2503 if (resp.value == 0)
2504 {
2505 break;
2506 }
2507 onedone = resp.value > req.length ? req.length : resp.value;
2508 MemCpy((char *)pBuffer + done, pConn->mem + sizeof(pConn->file), onedone);
2509 done += onedone;
2510 }
2511 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2512 *pulActual = done;
2513 } while (0);
2514 log("NdpFileRead <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc, pConn->rc);
2515
2516 return rc;
2517}
2518
2519int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2520{
2521 Connection *pConn = (Connection *)conn;
2522 Resource *pRes = pConn->pRes;
2523 int rc = 0;
2524 unsigned long done = 0;
2525 unsigned long onedone;
2526 unsigned long action;
2527 smb_request req = {0};
2528 smb_response resp = {0};
2529
2530 log("NdpFileWrite in\n");
2531 do {
2532 if (pConn->file.fd < 0)
2533 {
2534 rc = ERROR_INVALID_HANDLE;
2535 break;
2536 }
2537 if (pConn->rc)
2538 {
2539 rc = ERROR_PIPE_NOT_CONNECTED;
2540 break;
2541 }
2542
2543 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2544 req.request = SMBREQ_WRITE;
2545 req.param = pConn->mem;
2546 req.paramlen = sizeof(pConn->file);
2547
2548 while (done < ulWrite)
2549 {
2550 req.length = pRes->memlen - req.paramlen < (ulWrite - done) ? pRes->memlen - req.paramlen : (ulWrite - done);
2551 MemCpy(pConn->mem + sizeof(pConn->file), (char *)pBuffer + done, req.length);
2552 req.length += req.paramlen;
2553
2554 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2555 if (pConn->rc || action < sizeof(resp) || resp.rc)
2556 {
2557 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2558 break;
2559 }
2560 done += resp.value & 0xFFFFFFFF;
2561 if (resp.value < req.length)
2562 {
2563 break;
2564 }
2565 }
2566 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2567 *pulActual = done;
2568 } while (0);
2569 log("NdpFileWrite <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc, pConn->rc);
2570
2571 return rc;
2572}
Note: See TracBrowser for help on using the repository browser.