source: trunk-3.0/source/ndpsmb/ndpsmb.c@ 101

Last change on this file since 101 was 70, checked in by Yuri Dario, 18 years ago

Implemented automatic reconnection if pipe closes. Fixes ticket:32.

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