Index: /trunk/samba-3.0.25pre1/source/ndpsmb/h/hmacros.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/h/hmacros.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/h/hmacros.h	(revision 5)
@@ -0,0 +1,14 @@
+#define HEADING(a,b) :h##a res=##b group=2 x=left y=top width=100% \
+                     height=100% scroll=both.
+#define LINK(a,b) :link reftype=hd res=a.b:elink.
+#define PINDEX(a) :i1 id=a.
+#define SINDEX(a) :i2 refid=a.
+#define HP1(a) :hp1.##a##:ehp1.
+#define HP2(a) :hp2.##a##:ehp2.
+#define HP3(a) :hp3.##a##:ehp3.
+#define HP4(a) :hp4.##a##:ehp4.
+#define HP5(a) :hp5.##a##:ehp5.
+#define HP6(a) :hp6.##a##:ehp6.
+#define HP7(a) :hp7.##a##:ehp7.
+#define HP8(a) :hp8.##a##:ehp8.
+#define HP9(a) :hp9.##a##:ehp9.
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/h/mydebug.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/h/mydebug.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/h/mydebug.h	(revision 5)
@@ -0,0 +1,39 @@
+#ifndef _MY_DEBUG_
+#define _MY_DEBUG_ 1
+
+#ifdef DEBUG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+
+void log(const char *fmt, ...)
+{  
+	FILE * logfile = NULL;
+	va_list args;
+	time_t t = time(NULL);
+	char timebuf[80] = {0};
+	strftime(timebuf,sizeof(timebuf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
+	logfile = fopen("e:\\smblog","a");
+	if (logfile == NULL)
+	{
+		DosBeep(400,400);
+	}
+	else
+	{
+		fprintf(logfile, "%s: ", timebuf);
+		va_start(args, fmt);
+		vfprintf(logfile, fmt, args);    
+		va_end(args);
+		fclose(logfile);
+	}
+}
+
+#else
+
+#define log;
+
+#endif
+
+#endif /* _MY_DEBUG_ */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndextpl2.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndextpl2.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndextpl2.h	(revision 5)
@@ -0,0 +1,424 @@
+/* 
+ * NetDrive for OS/2 External Plugin's level 2 header file.
+ *
+ * (C) COPYRIGHT Blueprint Software Works, Inc. 1999-2004.
+ * ALL RIGHTS RESERVED. 
+ */
+
+#ifndef __EXTPL2__H
+#define __EXTPL2__H
+
+#include <ndfs.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#pragma pack(1)
+
+/* Plugin attributes */
+#define NDPA_REUSE_FILE_CONNECTIONS (0x1)
+
+#define DEFINE_HANDLE(a) struct _##a; typedef struct _##a *##a;
+
+#ifndef __EXTPL__H
+DEFINE_HANDLE(HRESOURCE)
+DEFINE_HANDLE(HCONNECTION)
+#endif
+
+DEFINE_HANDLE(NDPROPERTYHANDLE)
+DEFINE_HANDLE(NDMUTEX)
+DEFINE_HANDLE(NDFILEHANDLE)
+
+#define DOSATTR_READONLY	0x01
+#define DOSATTR_HIDDEN		0x02
+#define DOSATTR_SYSTEM		0x04
+#define DOSATTR_VOLLABEL        0x08
+#define DOSATTR_DIRECTORY	0x10
+#define DOSATTR_ARCHIVED	0x20
+#define DOSATTR_NON83		0x40
+
+#define DOSATTR_NEEDEA		0x80
+
+// flags for NDPLFILEINFO::ulFlags
+#define NDFILE_PARENT  (0x1)
+#define NDFILE_ROOT    (0x2)
+
+typedef struct _NDFILEINFO
+{
+    FILESTATUS3 stat;    // standard OS/2 file information
+    ULONG ulFlags;       // see NDFILE_PARENT, NDFILE_ROOT
+    UCHAR cchName;       // length of the file name
+    CHAR  *pszName;      // address of the name
+    CHAR  *pszUpperName; // address of the uppercased name
+} NDFILEINFO;
+
+typedef struct _NDFILEINFOL
+{
+    FILESTATUS3L stat;   // standard OS/2 file information
+    ULONG ulFlags;       // see NDFILE_PARENT, NDFILE_ROOT
+    UCHAR cchName;       // length of the file name
+    CHAR  *pszName;      // address of the name
+    CHAR  *pszUpperName; // address of the uppercased name
+} NDFILEINFOL;
+
+typedef struct _NDDATABUF
+{
+    ULONG ulSize;
+    void  *pData;
+} NDDATABUF;
+
+
+typedef struct _NDFSALLOCATE 
+{
+    ULONG   cSectorUnit;
+    ULONG   cUnit;
+    ULONG   cUnitAvail;
+    USHORT  cbSector;
+} NDFSALLOCATE;
+
+enum {
+    ND_PROP_STRING = 0,
+    ND_PROP_ULONG  = 1
+};
+
+typedef struct _NDPROPERTYINFO
+{
+    ULONG ulType;
+    ULONG ulReserved;
+    CHAR *szName;
+    CHAR *szDefaultValue;
+} NDPROPERTYINFO;
+
+/* defines for fsphWildMatch's ignorecase parameter */
+#define ND_CASE_SENSITIVE 0
+#define ND_IGNORE_CASE    1
+
+typedef struct _NDPATHELEMENT
+{
+    ULONG length;
+    CHAR  *name;
+    CHAR  *upperName;
+} NDPATHELEMENT;
+
+typedef struct _NDTIMEDATE
+{
+    int seconds;
+    int minutes;
+    int hours;
+    int day;
+    int month;
+    int year;
+} NDTIMEDATE;
+
+DEFINE_HANDLE(NDTIMEHANDLE)
+
+/*
+ * Logging levels
+ */
+#define ND_LL_DEBUG (5)
+#define ND_LL_INFO  (4)
+#define ND_LL_WARN  (3)
+#define ND_LL_ERROR (2)
+#define ND_LL_FATAL (1)
+#define ND_LL_NONE  (0)
+
+DEFINE_HANDLE(NDLOGHANDLE)
+
+#define NDMSGID(a) ((char *)(a & 0xFFFFul))
+
+typedef struct _PLUGINHELPERTABLE2
+{
+    ULONG cb;
+
+    int (PNDENTRY fsphQueryStringProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const CHAR **pvalue, ULONG *plen);
+    int (PNDENTRY fsphQueryUlongProperty) (NDPROPERTYHANDLE handle, const CHAR *name, ULONG *pvalue);
+    int (PNDENTRY fsphSetProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const CHAR *value);
+    int (PNDENTRY fsphParseProperty) (NDPROPERTYHANDLE handle, const CHAR *s);
+    
+    int (PNDENTRY fsphAddFileFind16) (void *plist, FILEFINDBUF *pFindBuf, int cEntries, void *data, ULONG dataLength, ULONG flags);
+    int (PNDENTRY fsphAddFileFind32) (void *plist, FILEFINDBUF3 *pFindBuf, void *data, ULONG dataLength, ULONG flags);
+    void (PNDENTRY fsphInitFileFindBuf3) (FILEFINDBUF3 *pbuf, FILESTATUS3 *pstat, char *name);
+
+    int (PNDENTRY fsphWildMatch) (const CHAR *pat, const CHAR *str, int ignorecase);
+    int (PNDENTRY fsphAttrMatch) (ULONG pat, ULONG attr);
+
+    int (PNDENTRY fsphSetResourceData) (void *plist, void *data, ULONG dataLength);
+    int (PNDENTRY fsphGetResourceData) (NDFILEINFO *pfi, NDDATABUF *pdata, int expectedSize);
+    int (PNDENTRY fsphGetFileInfoData) (NDFILEINFO *pfi, NDDATABUF *pdata, int expectedSize);
+
+    NDPATHELEMENT * (PNDENTRY fsphPathElemNext) (int index, NDPATHELEMENT *pel);
+    NDPATHELEMENT * (PNDENTRY fsphPathElemPrev) (int index, NDPATHELEMENT *pel);
+    NDPATHELEMENT * (PNDENTRY fsphNameElem) (int index);
+    int (PNDENTRY fsphIsLastElem) (int index, NDPATHELEMENT *pel);
+
+    int (PNDENTRY fsphUpperCase) (CHAR *str);
+    int (PNDENTRY fsphUpperCase2) (CHAR *str, int len);
+
+    int (PNDENTRY fsphGEA16to32) (GEALIST *fpGEAList, GEA2LIST *fpGEA2List);
+    int (PNDENTRY fsphGEA32to16) (GEA2LIST *fpGEA2List, GEALIST *fpGEAList);
+    int (PNDENTRY fsphFEA16to32) (FEALIST *fpFEAList, FEA2LIST *fpFEA2List);
+    int (PNDENTRY fsphFEA32to16) (FEA2LIST *fpFEA2List, FEALIST *fpFEAList);
+
+    int (PNDENTRY fsphGetCurrentDateTime) (FDATE *pDate, FTIME *pTime);
+    void (PNDENTRY fsphUnixTimeToDosDate) (ULONG time, FDATE *pd, FTIME *pt);
+    void (PNDENTRY fsphDosDateToUnixTime) (FDATE d, FTIME t, ULONG *ptime);
+    void (PNDENTRY fsphTimeUnix2TimeDate) (ULONG time, NDTIMEDATE *ptd);
+    void (PNDENTRY fsphTimeTimeDate2Unix) (NDTIMEDATE *ptd, ULONG *ptime);
+    int (PNDENTRY fsphTimeCreateHandle) (NDTIMEHANDLE *phandle, const CHAR *pTZ);
+    void (PNDENTRY fsphTimeDeleteHandle) (NDTIMEHANDLE handle);
+    void (PNDENTRY fsphTimeLocal2GMT) (NDTIMEHANDLE handle, NDTIMEDATE *plocal, NDTIMEDATE *pgmt);
+    void (PNDENTRY fsphTimeGMT2Local) (NDTIMEHANDLE handle, NDTIMEDATE *pgmt, NDTIMEDATE *plocal);
+    
+    INT    (PNDENTRY fsphCharIsDBCS) (CHAR c);
+    USHORT (PNDENTRY fsphLoadChar) (CHAR **pps);
+    CHAR * (PNDENTRY fsphCopyChar) (CHAR **pdst, CHAR *src);
+    CHAR * (PNDENTRY fsphStrChr) (const CHAR *pStr, CHAR c);
+    CHAR * (PNDENTRY fsphStrRChr) (const CHAR *pStr, CHAR c);
+    INT    (PNDENTRY fsphStrCmp) (const CHAR *s1, const CHAR *s2);
+    INT    (PNDENTRY fsphStrNCmp) (const CHAR *s1, const CHAR *s2, INT n);
+    INT    (PNDENTRY fsphStrICmp) (const CHAR *s1, const CHAR *s2);
+    INT    (PNDENTRY fsphStrNICmp) (const CHAR *s1, const CHAR *s2, INT n);
+    
+    INT (PNDENTRY fsphQueryFilePtr) (ULONG *pulFilePtr);
+    INT (PNDENTRY fsphQueryFileSize) (ULONG *pulFileSize);
+    INT (PNDENTRY fsphSetFilePtr) (ULONG ulFileSize, ULONG ulCurrent, LONG lOffset, ULONG ulMethod, ULONG *pulActual);
+    
+    INT (PNDENTRY fsphSetAttrPattern) (void *plist, ULONG ulAttribute);
+    
+    ULONG (PNDENTRY fsphQueryCurrentCp) (void);
+    
+    CHAR (PNDENTRY fsphCpTranslateChar) (ULONG idCpSource, CHAR cSource, ULONG idCpDest);
+    BOOL (PNDENTRY fsphCpTranslateString) (ULONG idCpSource, const CHAR *pszSource, ULONG idCpDest, ULONG cbLenDest, CHAR *pszDest);
+    
+    BOOL (PNDENTRY fsphAsciiToUnicode) (ULONG idCpSource, PSZ pszSource, ULONG cbLenDest, USHORT *pDest);
+    BOOL (PNDENTRY fsphUnicodeToAscii) (USHORT *pSource, ULONG idCpDest, ULONG cbLenDest, CHAR *pDest);
+    
+    INT (PNDENTRY fsphLogOpen) (NDLOGHANDLE *phandle, ULONG loglevel, const char *logfile, const char *msgfile);
+    void (PNDENTRY fsphLogMsg) (NDLOGHANDLE handle, ULONG ll, CHAR *msg, INT argc, ...);
+    void (PNDENTRY fsphLogClose) (NDLOGHANDLE handle);
+
+    INT (PNDENTRY fsphSetUlongProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const ULONG value);
+
+    void (PNDENTRY fsphLogMsg2) (NDLOGHANDLE handle, ULONG ll, CHAR *msg, INT argc, CHAR **args);
+
+    void * (PNDENTRY fsphAllocMem) (ULONG size);
+    void * (PNDENTRY fsphReallocMem) (void *p, ULONG size);
+    void (PNDENTRY fsphFreeMem) (void *p);
+
+    void (PNDENTRY fsphUlong2String) (ULONG number, CHAR *string, INT n, INT base);
+    void (PNDENTRY fsphLong2String) (LONG number, CHAR *string, INT n, INT base);
+    INT (PNDENTRY fsphString2Ulong) (const CHAR *string, CHAR **pstring2, ULONG *pvalue, INT base);
+    INT (PNDENTRY fsph_vsnprintf) (CHAR *buf, INT n, const CHAR *fmt, CHAR **args);
+    INT (PNDENTRY fsph_snprintf) (CHAR *buf, INT n, const CHAR *fmt, ...);
+    
+    INT (PNDENTRY fsphCreateMutex) (NDMUTEX *pmutex);
+    INT (PNDENTRY fsphRequestMutex) (NDMUTEX mutex, ULONG ulTimeout);
+    INT (PNDENTRY fsphReleaseMutex) (NDMUTEX mutex);
+    void (PNDENTRY fsphCloseMutex) (NDMUTEX mutex);
+
+    INT (PNDENTRY fsphQueryFileStatus) (FILESTATUS3 *pstat3);
+ 
+    INT (PNDENTRY fsphUniStrLen) (USHORT *str);
+    
+    INT (PNDENTRY fsphQueryFileOpenMode) (ULONG *pulOpenMode);
+} PLUGINHELPERTABLE2;
+
+// large files support (> 2Gb)
+typedef struct _PLUGINHELPERTABLE2L
+{
+    ULONG cb;
+
+    int (PNDENTRY fsphQueryStringProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const CHAR **pvalue, ULONG *plen);
+    int (PNDENTRY fsphQueryUlongProperty) (NDPROPERTYHANDLE handle, const CHAR *name, ULONG *pvalue);
+    int (PNDENTRY fsphSetProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const CHAR *value);
+    int (PNDENTRY fsphParseProperty) (NDPROPERTYHANDLE handle, const CHAR *s);
+    
+    int (PNDENTRY fsphAddFileFind16) (void *plist, FILEFINDBUF *pFindBuf, int cEntries, void *data, ULONG dataLength, ULONG flags);
+    int (PNDENTRY fsphAddFileFind32) (void *plist, FILEFINDBUF3 *pFindBuf, void *data, ULONG dataLength, ULONG flags);
+    void (PNDENTRY fsphInitFileFindBuf3) (FILEFINDBUF3 *pbuf, FILESTATUS3 *pstat, char *name);
+
+    int (PNDENTRY fsphWildMatch) (const CHAR *pat, const CHAR *str, int ignorecase);
+    int (PNDENTRY fsphAttrMatch) (ULONG pat, ULONG attr);
+
+    int (PNDENTRY fsphSetResourceData) (void *plist, void *data, ULONG dataLength);
+    int (PNDENTRY fsphGetResourceData) (NDFILEINFOL *pfi, NDDATABUF *pdata, int expectedSize);
+    int (PNDENTRY fsphGetFileInfoData) (NDFILEINFOL *pfi, NDDATABUF *pdata, int expectedSize);
+
+    NDPATHELEMENT * (PNDENTRY fsphPathElemNext) (int index, NDPATHELEMENT *pel);
+    NDPATHELEMENT * (PNDENTRY fsphPathElemPrev) (int index, NDPATHELEMENT *pel);
+    NDPATHELEMENT * (PNDENTRY fsphNameElem) (int index);
+    int (PNDENTRY fsphIsLastElem) (int index, NDPATHELEMENT *pel);
+
+    int (PNDENTRY fsphUpperCase) (CHAR *str);
+    int (PNDENTRY fsphUpperCase2) (CHAR *str, int len);
+
+    int (PNDENTRY fsphGEA16to32) (GEALIST *fpGEAList, GEA2LIST *fpGEA2List);
+    int (PNDENTRY fsphGEA32to16) (GEA2LIST *fpGEA2List, GEALIST *fpGEAList);
+    int (PNDENTRY fsphFEA16to32) (FEALIST *fpFEAList, FEA2LIST *fpFEA2List);
+    int (PNDENTRY fsphFEA32to16) (FEA2LIST *fpFEA2List, FEALIST *fpFEAList);
+
+    int (PNDENTRY fsphGetCurrentDateTime) (FDATE *pDate, FTIME *pTime);
+    void (PNDENTRY fsphUnixTimeToDosDate) (ULONG time, FDATE *pd, FTIME *pt);
+    void (PNDENTRY fsphDosDateToUnixTime) (FDATE d, FTIME t, ULONG *ptime);
+    void (PNDENTRY fsphTimeUnix2TimeDate) (ULONG time, NDTIMEDATE *ptd);
+    void (PNDENTRY fsphTimeTimeDate2Unix) (NDTIMEDATE *ptd, ULONG *ptime);
+    int (PNDENTRY fsphTimeCreateHandle) (NDTIMEHANDLE *phandle, const CHAR *pTZ);
+    void (PNDENTRY fsphTimeDeleteHandle) (NDTIMEHANDLE handle);
+    void (PNDENTRY fsphTimeLocal2GMT) (NDTIMEHANDLE handle, NDTIMEDATE *plocal, NDTIMEDATE *pgmt);
+    void (PNDENTRY fsphTimeGMT2Local) (NDTIMEHANDLE handle, NDTIMEDATE *pgmt, NDTIMEDATE *plocal);
+    
+    INT    (PNDENTRY fsphCharIsDBCS) (CHAR c);
+    USHORT (PNDENTRY fsphLoadChar) (CHAR **pps);
+    CHAR * (PNDENTRY fsphCopyChar) (CHAR **pdst, CHAR *src);
+    CHAR * (PNDENTRY fsphStrChr) (const CHAR *pStr, CHAR c);
+    CHAR * (PNDENTRY fsphStrRChr) (const CHAR *pStr, CHAR c);
+    INT    (PNDENTRY fsphStrCmp) (const CHAR *s1, const CHAR *s2);
+    INT    (PNDENTRY fsphStrNCmp) (const CHAR *s1, const CHAR *s2, INT n);
+    INT    (PNDENTRY fsphStrICmp) (const CHAR *s1, const CHAR *s2);
+    INT    (PNDENTRY fsphStrNICmp) (const CHAR *s1, const CHAR *s2, INT n);
+    
+    INT (PNDENTRY fsphQueryFilePtr) (LONGLONG *pllFilePtr);
+    INT (PNDENTRY fsphQueryFileSize) (LONGLONG *pllFileSize);
+    INT (PNDENTRY fsphSetFilePtr) (LONGLONG llFileSize, LONGLONG llCurrent, LONGLONG lOffset, ULONG ulMethod, LONGLONG *pllActual);
+    
+    INT (PNDENTRY fsphSetAttrPattern) (void *plist, ULONG ulAttribute);
+    
+    ULONG (PNDENTRY fsphQueryCurrentCp) (void);
+    
+    CHAR (PNDENTRY fsphCpTranslateChar) (ULONG idCpSource, CHAR cSource, ULONG idCpDest);
+    BOOL (PNDENTRY fsphCpTranslateString) (ULONG idCpSource, const CHAR *pszSource, ULONG idCpDest, ULONG cbLenDest, CHAR *pszDest);
+    
+    BOOL (PNDENTRY fsphAsciiToUnicode) (ULONG idCpSource, PSZ pszSource, ULONG cbLenDest, USHORT *pDest);
+    BOOL (PNDENTRY fsphUnicodeToAscii) (USHORT *pSource, ULONG idCpDest, ULONG cbLenDest, CHAR *pDest);
+    
+    INT (PNDENTRY fsphLogOpen) (NDLOGHANDLE *phandle, ULONG loglevel, const char *logfile, const char *msgfile);
+    void (PNDENTRY fsphLogMsg) (NDLOGHANDLE handle, ULONG ll, CHAR *msg, INT argc, ...);
+    void (PNDENTRY fsphLogClose) (NDLOGHANDLE handle);
+
+    INT (PNDENTRY fsphSetUlongProperty) (NDPROPERTYHANDLE handle, const CHAR *name, const ULONG value);
+
+    void (PNDENTRY fsphLogMsg2) (NDLOGHANDLE handle, ULONG ll, CHAR *msg, INT argc, CHAR **args);
+
+    void * (PNDENTRY fsphAllocMem) (ULONG size);
+    void * (PNDENTRY fsphReallocMem) (void *p, ULONG size);
+    void (PNDENTRY fsphFreeMem) (void *p);
+
+    void (PNDENTRY fsphUlong2String) (ULONG number, CHAR *string, INT n, INT base);
+    void (PNDENTRY fsphLong2String) (LONG number, CHAR *string, INT n, INT base);
+    INT (PNDENTRY fsphString2Ulong) (const CHAR *string, CHAR **pstring2, ULONG *pvalue, INT base);
+    INT (PNDENTRY fsph_vsnprintf) (CHAR *buf, INT n, const CHAR *fmt, CHAR **args);
+    INT (PNDENTRY fsph_snprintf) (CHAR *buf, INT n, const CHAR *fmt, ...);
+    
+    INT (PNDENTRY fsphCreateMutex) (NDMUTEX *pmutex);
+    INT (PNDENTRY fsphRequestMutex) (NDMUTEX mutex, ULONG ulTimeout);
+    INT (PNDENTRY fsphReleaseMutex) (NDMUTEX mutex);
+    void (PNDENTRY fsphCloseMutex) (NDMUTEX mutex);
+
+    INT (PNDENTRY fsphQueryFileStatus) (FILESTATUS3L *pstat);
+ 
+    INT (PNDENTRY fsphUniStrLen) (USHORT *str);
+    
+    INT (PNDENTRY fsphQueryFileOpenMode) (ULONG *pulOpenMode);
+    
+    int (PNDENTRY fsphAddFile32L) (void *plist, FILESTATUS3L *pstat, char *name, ULONG namelen, void *data, ULONG dataLength, ULONG flags);
+    
+    USHORT (PNDENTRY fsphGetChar) (const char *p);
+    const char * (PNDENTRY fsphNextChar) (const char *p);
+    
+    INT (PNDENTRY fsphString2longlong) (const CHAR *string, CHAR **pstring2, long long *pvalue, INT base);
+    
+    int (PNDENTRY fsphTimeDateToUnixTime) (const NDTIMEDATE *ptimedate, unsigned long *ptimelow, unsigned long *ptimehigh, int isgmt, int togmt);
+
+    int (PNDENTRY fsphGetCurrentDateTime2) (NDTIMEDATE *ptimedate);
+} PLUGINHELPERTABLE2L;
+
+#pragma pack()
+
+// flags for NdpRsrcQueryInfo pulFlags parameter
+#define ND_RSRC_AVAILABLE (1)
+
+// return codes for NdpRsrcCompare
+#define ND_RSRC_EQUAL     (0)
+#define ND_RSRC_DIFFERENT (1)
+
+
+// Plugin Entry points
+#ifdef NDPL_LARGEFILES
+#define PLUGINHELPERTABLE2 PLUGINHELPERTABLE2L
+#define NDFILEINFO NDFILEINFOL
+#endif
+
+extern const char *NdpTypes[];
+extern const NDPROPERTYINFO *NdpPropertiesInfo[];
+extern const unsigned long NdpAttribute;
+int NDENTRY NdpPluginLoad (PLUGINHELPERTABLE2 *pPHT2);
+int NDENTRY NdpPluginFree (void);
+            
+/* resource functions */
+int NDENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties);
+int NDENTRY NdpFreeResource (HRESOURCE resource);
+int NDENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn);
+int NDENTRY NdpFreeConnection (HCONNECTION conn);
+
+int NDENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2);
+int NDENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2);
+
+int NDENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen);
+int NDENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *in, ULONG insize, PULONG poutlen);
+int NDENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa);
+      
+/* path functions */
+int NDENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath);
+int NDENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFO *pfi);
+int NDENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf);
+int NDENTRY NdpRefresh (HCONNECTION conn, char *path, int tree);
+int NDENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFO *pfi, char *szPathName);
+int NDENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFO *pfi, FEALIST *pFEAList);
+int NDENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFO *pfi);
+int NDENTRY NdpEASize (HCONNECTION conn, NDFILEINFO *pfi, ULONG *pulEASize);
+int NDENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFO *pfi, char *szPath);
+int NDENTRY NdpCopy (HCONNECTION conn, NDFILEINFO *pfiDst, char *szDst, NDFILEINFO *pfiSrc, char *szSrc, ULONG ulOption);
+int NDENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFO *pfiDst, char *szDst, NDFILEINFO *pfiSrc, char *szSrc, ULONG ulOption);
+int NDENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFO *pfi, char *szFile);
+int NDENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFO *pfiparent, char *szDirName, FEALIST *pFEAList);
+int NDENTRY NdpFindStart (HCONNECTION conn, void *pList, NDFILEINFO *pfiparent, char *szPath, ULONG ulAttribute);
+int NDENTRY NdpMove (HCONNECTION conn, NDFILEINFO *pfiDst, char *szDst, NDFILEINFO *pfiSrc, char *szSrc);
+int NDENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFO *pfiDst, char *szDst, NDFILEINFO *pfiSrc, char *szSrc);
+int NDENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFO *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen);
+int NDENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFO *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen);
+int NDENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA);
+int NDENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList);
+int NDENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList);
+int NDENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFO *pfi, char *szDir);
+int NDENTRY NdpFlush (HRESOURCE resource);
+int NDENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFO *pfi, char *szFileName, USHORT usAttr);
+int NDENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function,
+                       void *in, ULONG insize, PULONG poutlen);
+                                      
+/* file functions */
+int NDENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist);
+int NDENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList);
+int NDENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList);
+int NDENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize);
+int NDENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFO *pfi);
+int NDENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual);
+int NDENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle);
+int NDENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle);
+int NDENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen);
+int NDENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual);
+int NDENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual);
+
+// large file support (>2Gb) 
+#ifdef NDPL_LARGEFILES
+int NDENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList);
+int NDENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList);
+int NDENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual);
+int NDENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen);
+#endif
+
+#ifdef __cplusplus
+    }
+#endif
+
+#endif /* __EXTPL2__H */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndfs.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndfs.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndfs.h	(revision 5)
@@ -0,0 +1,416 @@
+/*
+ * NetDrive File System (NDFS)
+ *
+ * Version 2.3.x
+ *
+ * (C) COPYRIGHT Blueprint Software Works, Inc. 1999-2004.
+ * ALL RIGHTS RESERVED. 
+ */
+
+#ifndef __NDFS__H
+#define __NDFS__H
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#if defined(__IBMC__) || defined(__IBMCPP__)
+#define FNPTR(a) * a
+#else
+#define FNPTR(a) a *
+#endif
+
+#define NDENTRY APIENTRY
+#define PNDENTRY FNPTR(NDENTRY)
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+    /* This is the file system ID as in DOSQUERYFSINFO */
+    #define NDFS_ID              0x21401785UL
+    
+    /* Maximum length of a type name, including trailing '\0',
+     * i.e. len is up to 7 characters and one nul character
+     */
+    #define ND_MAX_TYPE_SIZE     8
+
+    /* resource independent flags for NdpMount */
+    #define ND_FLAG_WRITEPROTECT      0x1
+    #define ND_FLAG_CHECKDUPLICATE    0x2
+    
+    /* mount points flags */
+    #define ND_MP_FLAG_NORMAL         0x0
+    
+    /* NdQueryInfo infolevels */
+    #define ND_INFO_IFS            0
+    #define ND_INFO_CTL            1
+    #define ND_INFO_NDFS_PATH      2
+    #define ND_INFO_DRIVES         3
+    
+    #pragma pack(1)
+    typedef struct _RIDINFO
+    {
+        ULONG  ulReqCompleted;
+        USHORT usReqMax;
+        USHORT usReqInProcess;
+        USHORT usReqMaxInProcess;
+        USHORT usReqRetCnt;
+        USHORT usReqCptCnt;
+        ULONG  ulFreeHits;
+        ULONG  ulCptHits;
+        ULONG  ulFreeFaults;
+        ULONG  ulCptFaults;
+        ULONG  ulFreeScanned;
+        ULONG  ulCptScanned;
+    } RIDINFO;
+    
+    typedef struct _IFSINFO
+    {
+        CHAR    achName[8];
+        USHORT  usVerMajor;
+        USHORT  usVerMinor;
+        RIDINFO ridInfo;
+        USHORT  usCpgmConnected;
+        USHORT  usCpgmPID;
+    } IFSINFO;
+    
+    typedef struct _CTLINFO
+    {
+        USHORT  usCpgmConnected;
+        USHORT  usCpgmPID;
+        ULONG   ulVersion;
+    } CTLINFO;
+    
+    typedef struct _NDFSPATHINFO
+    {
+        CHAR achNDFSPath[CCHMAXPATH];
+    } NDFSPATHINFO;
+
+    #pragma pack()
+
+
+    APIRET NDENTRY  NdQueryInfo (ULONG infolevel,
+                                  PVOID pBuf,
+                                  PULONG pcbBuf);
+                                 
+    APIRET NDENTRY  NdAttach (PSZ pszDevice,
+                               PSZ pszLabel,
+                               ULONG cUnit,
+                               ULONG cUnitAvail);
+
+    APIRET NDENTRY  NdDetach (PSZ pszDevice);
+    
+    APIRET NDENTRY  NdSetDriveInfo (PSZ pszDevice,
+                                     ULONG cUnit,
+                                     ULONG cUnitAvail);
+                                     
+    APIRET NDENTRY  NdMount (PSZ pszType,
+                              ULONG ulFlags,
+                              PSZ pszDest, 
+                              PSZ pszSrc);
+
+    APIRET NDENTRY  NdRemount (PSZ pszType,
+                                ULONG ulIndex,
+                                ULONG ulFlags,
+                                PSZ pszDest, 
+                                PSZ pszSrc);
+
+    APIRET NDENTRY  NdUnmount (PSZ pszDest, 
+                                ULONG ulIndex);
+
+    APIRET NDENTRY  NdIoctl (ULONG ulFunction,
+                              PSZ pszDest, 
+                              PVOID pData, 
+                              ULONG ulDataLenIn,
+                              PULONG pulDataLenOut);
+                              
+    APIRET NDENTRY  NdPluginIoctl (ULONG ulFunction,
+                                    PSZ pszPlugin, 
+                                    PSZ pszRsrcType, 
+                                    PSZ pszDest, 
+                                    PVOID pData, 
+                                    ULONG ulDataLenIn,
+                                    PULONG pulDataLenOut);
+
+    APIRET NDENTRY NdCreateMountPoint (PSZ pszPath,
+                                        ULONG ulFlags);
+    
+    APIRET NDENTRY NdDeleteMountPoint (PSZ pszPath);
+    
+    APIRET NDENTRY NdKill (VOID);
+    
+    APIRET NDENTRY NdLoadPlugin (PSZ pszName);
+
+    APIRET NDENTRY NdFreePlugin (PSZ pszName);
+
+    #define ORD_NDQUERYINFO           1
+    #define ORD_NDATTACH              2
+    #define ORD_NDDETACH              3
+    #define ORD_NDSETDRIVEINFO        4
+    #define ORD_NDMOUNT               5
+    #define ORD_NDUNMOUNT             6
+    #define ORD_NDIOCTL               7
+    #define ORD_NDCREATEMOUNTPOINT    8
+    #define ORD_NDDELETEMOUNTPOINT    9
+    #define ORD_NDKILL               10
+    #define ORD_NDLOADPLUGIN         11
+    #define ORD_NDFREEPLUGIN         12
+    #define ORD_NDPLUGINIOCTL        14
+    #define ORD_NDREMOUNT            15
+    
+
+        /* IOCTL functions */
+        /* Path related function, pszDest != NULL */
+        #define ND_IOCTL_QUERYMOUNTPOINT        0
+        #define ND_IOCTL_QUERYMOUNTINFO         1
+        #define ND_IOCTL_REFRESH                2
+        #define ND_IOCTL_QUERYMOUNTINFOSHORT    3
+        /* 4 is obsoleted */
+        #define ND_IOCTL_RSRCINFO               5
+        #define ND_IOCTL_REFRESHTREE            6
+        #define ND_IOCTL_QUERYPATHINFO          7
+        #define ND_IOCTL_SETWRITEPROTECT        8
+        
+        /* Plugin related function, pszDest == NULL */
+        #define ND_IOCTL_QUERYPLUGINS         100
+        #define ND_IOCTL_QUERYRSRCTYPES       101
+        #define ND_IOCTL_QUERYTYPEINFO        102
+
+        
+        #pragma pack(1)
+        
+        /* IOCTL in and out data */
+        
+        /* ND_IOCTL_QUERYMOUNTPOINT: 
+         *   Query if the specified path is an existing mount point.
+         */
+        /* no in */
+        /* no out */
+        
+        
+        /* ND_IOCTL_QUERYMOUNTINFO:
+         *   Query mounted resources and child mount point information
+         *   on the specified mount point path.
+         */
+        /* no in */
+        /* out */
+        typedef struct _ND_DATA_MOUNTINFO        
+        {
+            USHORT usMountPointsTotal;
+            USHORT usMountPointsReturned;
+            USHORT usResourcesTotal;
+            USHORT usResourcesReturned;
+            ULONG  cbName;      /* length of the name without the trailing '\0' */
+            CHAR   achName[1];  /* name of the mount point */
+            /* usMountPointsReturned ND_DATA_MOUNTPOINT structures */
+            /* usResourcesReturned ND_DATA_MOUNTRESOURCE structures */
+        } ND_DATA_MOUNTINFO;
+        typedef ND_DATA_MOUNTINFO *PND_DATA_MOUNTINFO;
+        
+        typedef struct _ND_DATA_MOUNTPOINT
+        {
+            ULONG  cbName;      /* length of the name without the trailing '\0' */
+            CHAR   achName[1];  /* name of the mount point */
+        } ND_DATA_MOUNTPOINT;
+        typedef ND_DATA_MOUNTPOINT *PND_DATA_MOUNTPOINT;
+        
+        typedef struct _ND_DATA_MOUNTRESOURCE
+        {
+            CHAR   achType[ND_MAX_TYPE_SIZE]; /* asciiz type of the resource */
+            ULONG  ulFlags;         /* resource flags, 
+                                     * low 16 bit - resource independent, 
+                                     * high 16 bit - resource private flags 
+                                     */
+            ULONG  cbData;          /* length of the data without the trailing '\0' */
+            CHAR   achData[1];      /* resource data */
+        } ND_DATA_MOUNTRESOURCE;
+        typedef ND_DATA_MOUNTRESOURCE *PND_DATA_MOUNTRESOURCE;
+        
+        
+        /* ND_IOCTL_REFRESH:
+         *   Refresh content of the specified directory. Allows to invalidate
+         *   cache for this directory listing.
+         */
+        /* no in */
+        /* no out */
+         
+        
+        /* ND_IOCTL_QUERYMOUNTINFOSHORT:
+         *   Query mounted resources and child mount point numbers
+         *   on the specified mount point path.
+         */
+        /* no in */
+        /* out */
+        typedef struct _ND_DATA_MOUNTINFOSHORT
+        {
+            USHORT usMountPointsTotal;
+            USHORT usResourcesTotal;
+            ULONG  cbName;        /* length of the name without the trailing '\0' */
+            CHAR   achName[CCHMAXPATH]; /* name of the mount point */
+        } ND_DATA_MOUNTINFOSHORT;
+        typedef ND_DATA_MOUNTINFOSHORT *PND_DATA_MOUNTINFOSHORT;
+        
+        
+        /* ND_IOCTL_RSRCINFO:
+         *   Query information about resource with specified index in the
+         *   specified mount point.
+         */
+        /* in */
+        typedef struct _ND_PARAM_INDEX
+        {
+            ULONG ulIndex; /* index of resource */
+        } ND_PARAM_INDEX;
+        /* out */
+        typedef struct _ND_DATA_RSRCINFO
+        {
+            ULONG  ulType;       /* numeric value of resource type, index in types array */
+            ULONG  ulFlags;      /* flags of the resource */
+            ULONG  cbData;       /* length of achData without trailing '\0' */
+            BYTE   cbType;       /* length of achType without trailing '\0' */
+            BYTE   bExternal;    /* =1 if external plugin */
+            BYTE   cbPlugin;     /* length of achPlugin without trailing '\0' */
+            CHAR   achType[1];   /* type of resource */
+            CHAR   achPlugin[1]; /* name of plugin */
+            CHAR   achData[1];   /* resource data */
+        } ND_DATA_RSRCINFO;
+        
+        #define RSRCINFO_SIZE(p) (sizeof (*p) + p->cbData + p->cbType + p->cbPlugin)
+        #define RSRCINFO_TYPE(p) (&(p->achType[0]))
+        #define RSRCINFO_PLUGIN(p) (RSRCINFO_TYPE(p) + sizeof (p->achType) + p->cbType)
+        #define RSRCINFO_DATA(p) (RSRCINFO_PLUGIN(p) + sizeof (p->achPlugin) + p->cbPlugin)
+        
+        #define RSRC_TYPE_ERROR 0xFFFF0000L
+        
+         
+        /* ND_IOCTL_REFRESHTREE:
+         *   Refresh content of the specified directory and its descendants. 
+         *   Allows to invalidate cache for the whole tree.
+         */
+        /* no in */
+        /* no out */
+         
+         
+        /* ND_IOCTL_QUERYPATHINFO:
+         *   Query NetDrive path information.
+         */
+        /* no in */
+        /* out */
+        typedef struct _ND_DATA_QUERYPATHINFO        
+        {
+            USHORT cb;           /* size of the structure including the cb */
+            BYTE   bPathType;    /* see ND_PT_* */
+            ULONG  ulType;       /* numeric value of resource type */
+            ULONG  ulIndex;      /* index of resource */
+            BYTE   cbType;       /* length of achType without trailing '\0' */
+            BYTE   cbPlugin;     /* length of achPlugin without trailing '\0' */
+            BYTE   cbMountPoint; /* length of achMountPoint without trailing '\0' */
+            BYTE   cbRsrcPath;   /* length of achRsrcPath without trailing '\0' */
+            CHAR   achType[1];   /* type name */
+            CHAR   achPlugin[1]; /* plugin name */
+            CHAR   achMountPoint[1]; /* mount point path */
+            CHAR   achRsrcPath[1]; /* path after mount point */
+        } ND_DATA_QUERYPATHINFO;
+        typedef ND_DATA_QUERYPATHINFO *PND_DATA_QUERYPATHINFO;
+        
+        /* Values for ND_DATA_QUERYPATHINFO::bPathType */
+        #define ND_PT_MOUNTPOINT 0
+        #define ND_PT_INTERNAL   1
+        #define ND_PT_EXTERNAL   2
+        
+        #define PATHINFO_SIZE(p) (sizeof (*p) + p->cbType + p->cbPlugin + p->cbMountPoint + p->cbRsrcPath)
+        #define PATHINFO_TYPE(p) (&(p->achType[0]))
+        #define PATHINFO_PLUGIN(p) (PATHINFO_TYPE(p) + sizeof (p->achType) + p->cbType)
+        #define PATHINFO_MOUNTPOINT(p) (PATHINFO_PLUGIN(p) + sizeof (p->achPlugin) + p->cbPlugin)
+        #define PATHINFO_RSRCPATH(p) (PATHINFO_MOUNTPOINT(p) + sizeof (p->achMountPoint) + p->cbMountPoint)
+        
+        
+        /* ND_IOCTL_SETWRITEPROTECT:
+         *   Sets write protect flag for resource with specified index in the
+         *   specified mount point.
+         */
+        /* in */
+        typedef struct _ND_PARAM_SETWRITEPROTECT
+        {
+            ULONG ulIndex;       /* index of resource */
+            ULONG fWriteProtect; /* 1 - write protect, 0 - write enable */
+        } ND_PARAM_SETWRITEPROTECT;
+        /* no out */
+        
+        
+        /* ND_IOCTL_QUERYPLUGINS:
+         *   Queries list of loaded plugins.
+         */
+        /* no in */
+        /* out */
+        typedef struct _ND_DATA_PLUGINLIST
+        {
+            ULONG cbSize;   /* size of plugin list (with ND_DATA_PLUGINLIST) */
+            ULONG ulCount;  /* number of plugins returned */
+            /* ulCount ND_DATA_PLUGIN structures follow */
+        } ND_DATA_PLUGINLIST;
+        
+        typedef struct _ND_DATA_PLUGIN
+        {
+            HMODULE hMod;       /* placeholder, always zero */
+            BYTE    bExternal;  /* = 1 if external plugin; 0 if internal */
+            BYTE    cbName;     /* length of the name without the trailing '\0' */
+            CHAR    szName[1];  /* plugin dll: ndpftp.dll -> name == ndpftp */
+        } ND_DATA_PLUGIN;
+        
+        
+        /* ND_IOCTL_QUERYRSRCTYPES:
+         *   Query type names for specified plugin.
+         */
+        /* in */
+        typedef struct _ND_PARAM_QUERYRSRCTYPES
+        {
+            BYTE cbName;        /* length of the name without the trailing '\0' */
+            char szName[1];     /* plugin name */
+        } ND_PARAM_QUERYRSRCTYPES;
+        /* out */
+        typedef struct _ND_DATA_RSRCTYPELIST
+        {
+            ULONG cbSize;   /* size of type list (with ND_DATA_RSRCTYPELIST) */
+            ULONG ulCount;  /* number of types returned */
+            /* ulCount ND_DATA_RSRCTYPE structures follow */
+        } ND_DATA_RSRCTYPELIST;
+        
+        typedef struct _ND_DATA_RSRCTYPE
+        {
+            BYTE    cbType;     /* length of the name without the trailing '\0' */
+            CHAR    szType[1];  /* type: local, ftp ... */
+        } ND_DATA_RSRCTYPE;
+        
+        
+        /* ND_IOCTL_QUERYTYPEINFO:
+         *   Query plugin name that supports the specified type.
+         */
+        /* in */
+        typedef struct _ND_PARAM_NAME
+        {
+            BYTE cbName;      /* length of the name without the trailing '\0' */
+            CHAR achName[1];  /* the type name */
+        } ND_PARAM_NAME;
+        /* out */
+        typedef struct _ND_DATA_TYPEINFO
+        {
+            ULONG  ulType;       /* numeric value of resource type, index in types array */
+            BYTE   cbType;       /* length of achType without trailing '\0' */
+            BYTE   cbPlugin;     /* length of achPlugin without trailing '\0' */
+            BYTE   bExternal;    /* = 1 if external plugin */
+            CHAR   achType[1];   /* type name */
+            CHAR   achPlugin[1]; /* plugin name */
+        } ND_DATA_TYPEINFO;
+        
+        #define TYPEINFO_SIZE(p) (sizeof (*p) + p->cbType + p->cbPlugin)
+        #define TYPEINFO_TYPE(p) (&(p->achType[0]))
+        #define TYPEINFO_PLUGIN(p) (TYPEINFO_TYPE(p) + sizeof (p->achType) + p->cbType)
+        
+        #pragma pack()
+
+#ifdef __cplusplus
+    }
+#endif
+
+#endif /* __NDFS__H */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndpl_rc.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndpl_rc.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/h/ndpl_rc.h	(revision 5)
@@ -0,0 +1,22 @@
+#ifndef __NDPL_RC__H
+#define __NDPL_RC__H
+
+#define BTN_HELP  10
+#define BTN_PREV  11
+
+
+#define NDRC_PLUGIN_NAME     1
+#define NDRC_PLUGIN_DESC     2
+#define NDRC_PLUGIN_HELP     3
+
+#define NDRC_TYPE_FIRST      100
+#define NDRC_TYPE_HELP_FIRST 300
+
+#define NDRC_TYPE_DLG_FIRST  1000
+
+#define PARM_REQUIRED 0x8000
+
+#define PARMTYPE_STRING 0
+#define PARMTYPE_INT    1
+
+#endif /* __NDPL_RC__H */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/iconvbug.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/iconvbug.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/iconvbug.c	(revision 5)
@@ -0,0 +1,169 @@
+// special iconv for smbd
+
+//#include <os2emx.h>
+#include <uconv.h>
+
+typedef struct _iconv_t
+{
+	int way; // 0 - to ucs, 1 - from ucs
+	UniChar ucp[20];
+} *iconv_t;
+
+/* Tell "iconv.h" to not define iconv_t by itself.  */
+#define _ICONV_T
+
+#include "includes.h"
+
+/* Convert an encoding name to te form understood by UniCreateUconvObject.  */
+static void __convert_codepage (const char *cp, UniChar *ucp)
+{
+  size_t sl = 0;
+
+  if (!stricmp (cp, "SYSTEM"))
+    return;
+  else if (!stricmp (cp, "EUC-JP"))
+    memcpy (ucp, L"IBM-954", 8*2);
+  else if (!stricmp (cp, "EUC-KR"))
+    memcpy (ucp, L"IBM-970", 8*2);
+  else if (!stricmp (cp, "EUC-TW"))
+    memcpy (ucp, L"IBM-964", 8*2);
+  else if (!stricmp (cp, "EUC-CN"))
+    memcpy (ucp, L"IBM-1383", 9*2);
+  else if (!stricmp (cp, "BIG5"))
+    memcpy (ucp, L"IBM-950", 8*2);
+  else if (!stricmp (cp, "UCS-2LE"))
+    memcpy (ucp, L"IBM-1200", 9*2);
+  else
+    {
+      /* Transform CPXXX naming style to IBM-XXX style */
+      if ((cp[0] == 'C' || cp[0] == 'c') && (cp[1] == 'P' || cp[1] == 'p'))
+        {
+          ucp[sl++] = 'I';
+          ucp[sl++] = 'B';
+          ucp[sl++] = 'M';
+          ucp[sl++] = '-';
+          cp += 2;
+        }
+
+      while (*cp != '\0')
+        ucp[sl++] = *cp++;
+      ucp[sl] = 0;
+    }
+}
+
+iconv_t
+iconv_open (const char *cp_to, const char *cp_from)
+{
+	UniChar *ucp;
+	char * cp;
+	iconv_t conv;
+	uconv_attribute_t attr;
+	UconvObject uo;
+
+	if (!cp_to || !cp_from)
+	{
+		errno = EINVAL;
+		return (iconv_t)(-1);
+	}
+
+	conv = (iconv_t)calloc(sizeof (struct _iconv_t), 1);
+	if (conv == NULL)
+	{
+		errno = ENOMEM;
+		return (iconv_t)(-1);
+	}
+
+	if (!stricmp (cp_to, "UCS-2LE"))
+	{
+		cp = (char *)cp_from;
+		conv->way = 0;
+	} else
+	if (!stricmp (cp_from, "UCS-2LE"))
+	{
+		cp = (char *)cp_to;
+		conv->way = 1;
+	} else
+	{
+		// samba never calls so
+		errno = EINVAL;
+		return (iconv_t)(-1);
+	}
+	__convert_codepage(cp, conv->ucp);
+	if (UniCreateUconvObject(conv->ucp, &uo))
+	{
+		free (conv);
+		errno = EINVAL;
+		return (iconv_t)(-1);
+	}
+	UniFreeUconvObject(uo);
+
+	return conv;
+}
+
+size_t
+iconv (iconv_t conv,
+       char **in, size_t *in_left,
+       char **out, size_t *out_left)
+{
+	int rc;
+	size_t sl;
+	size_t retval = 0;
+	UconvObject uo;
+
+	/* The caller wishes to reset iconv state by calling 
+	   iconv(conv, NULL, NULL, NULL, NULL). We should handle it */
+	if (!in || !in_left || !out || !out_left)
+	{
+		return 0;
+	}
+	if (UniCreateUconvObject(conv->ucp, &uo))
+	{
+		errno = EINVAL;
+		return (size_t)(-1);
+	}
+
+	if (conv->way)
+	{
+		sl = (*in_left) >> 1;
+		rc = UniUconvFromUcs (uo, (UniChar **)in, &sl, (void **)out, out_left, &retval);
+		*in_left = sl << 1;
+	}
+	else
+	{
+		sl = (*out_left) >> 1;
+		rc = UniUconvToUcs (uo, (void **)in, in_left, (UniChar **)out, &sl, &retval);
+		*out_left = sl << 1;
+	}
+
+	UniFreeUconvObject(uo);
+	if (!rc)
+	{
+		return retval;
+	}
+	switch (rc)
+	{
+		case ULS_ILLEGALSEQUENCE:
+			errno = ESPIPE;
+			break;
+		case ULS_INVALID:
+			errno = EINVAL;
+			break;
+		case ULS_BUFFERFULL:
+			errno = E2BIG;
+			break;
+		default:
+			errno = EBADF;
+			break;
+	}
+	return (size_t)(-1);
+}
+
+int
+iconv_close (iconv_t conv)
+{
+	if (conv && conv != (iconv_t)(-1))
+	{
+		free (conv);
+	}
+	return 0;
+}
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/instpl.cmd
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/instpl.cmd	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/instpl.cmd	(revision 5)
@@ -0,0 +1,1 @@
+nd.exe plugin install ndpsmb.ndp
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/make.cmd
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/make.cmd	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/make.cmd	(revision 5)
@@ -0,0 +1,20 @@
+@ECHO OFF
+SET PATH_EMXPGCC=D:\UTIL\emx\innotek\usr
+SET CCENV=EMX
+SET BUILD_ENV=EMX
+SET BUILD_PLATFORM=OS2
+SET DPATH=D:\UTIL\emx\innotek\usr\lib;D:\MPTN;D:\IBMCOM;D:\ibmcpp\help;D:\ibmcpp\locale;D:\ibmcpp\toolkit\msg;D:\Ibmcpp\Runtime;D:\IBMLAN\NETPROG;D:\IBMLAN;D:\MUGLIB;D:\OS2;D:\OS2\SYSTEM;D:\OS2\MDOS\WINOS2;D:\OS2\INSTALL;D:\;D:\OS2\BITMAP;D:\OS2\MDOS;D:\OS2\APPS;D:\MMOS2;D:\MMOS2\INSTALL;D:\IBMINST;D:\IBM386FS;D:\UTIL\ODIN;D:\UTIL\SVDISK;D:\UTIL\EMX\BOOK;
+SET PATH=D:\UTIL\emx\innotek\usr\i386-pc-os2-emx\bin;D:\UTIL\emx\innotek\usr\bin;D:\UTIL\EMX\UTIL;D:\MPTN\BIN;D:\IBMCOM;D:\ibmcpp\bin;D:\ibmcpp\toolkit\bin;D:\IBMMIZOLLA;D:\ORAOS2\XBIN;D:\IBMLAN\NETPROG;D:\MUGLIB;D:\NETSCAPE\PROGRAM;D:\TCPIP\BIN;D:\IBMGSK40\BIN;D:\IBMGSK\BIN;D:\OS2;D:\OS2\SYSTEM;D:\OS2\MDOS\WINOS2;D:\OS2\INSTALL;D:\;D:\OS2\MDOS;D:\OS2\APPS;D:\JAVA131\JRE\BIN;D:\JAVA11\BIN;D:\MMOS2;D:\IBM386FS;D:\UTIL\ARCHIV;D:\UTIL\GTU40;D:\UTIL\emx\vim\vim61;D:\UTIL\EMX\BIN;D:\FC;D:\OS2\CYRILLIC;D:\UTIL\SVDISK;D:\UTIL\EMX\UTIL;D:\UTIL\EMTEX\BIN;D:\UTIL\WATCHCAT;D:\UTIL\NICE\BIN;D:\UTIL\HIEW;D:\UTIL\ODIN;D:\UTIL\EMX\PERL\BIN;D:\util\CSS\os2;D:\TCPIP\ndfs;D:\LOTUSW4\COMPNENT;D:\LOTUSW4\WORDPRO;d:\DAMOBILE\bin;D:\TCPIP\NDFS;;
+SET C_INCLUDE_PATH=D:/UTIL/emx/innotek/usr/lib/gcc-lib/i386-pc-os2-emx/3.3.5/include;D:/UTIL/emx/innotek/usr/include
+SET CPLUS_INCLUDE_PATH=D:/UTIL/emx/innotek/usr/include/c++/3.3.5/;D:/UTIL/emx/innotek/usr/include/c++/3.3.5/i386-pc-os2-emx;D:/UTIL/emx/innotek/usr/include/c++/3.3.5/backward;D:/UTIL/emx/innotek/usr/include
+SET LIBRARY_PATH=D:/UTIL/emx/innotek/usr/lib/gcc-lib/i386-pc-os2-emx/3.3.5;D:/UTIL/emx/innotek/usr/lib;
+SET INFOPATH=D:/UTIL/emx/innotek/usr/info;d:/util/emx/info
+SET PROTODIR=D:/UTIL/emx/innotek/usr/include/c++/gen
+SET EMXOMFLD_TYPE=
+SET EMXOMFLD_LINKER=
+SET BEGINLIBPATH=D:\UTIL\emx\innotek\usr\lib
+SET BUILD_MODE=RELEASE
+@ECHO ON
+gcc -DTESTING -v %1
+rem -lsocket_l -liconv_l
+rem gcc -v %1
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/makefile
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/makefile	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/makefile	(revision 5)
@@ -0,0 +1,43 @@
+TOOLKIT = D:\ibmcpp\TOOLKIT
+NLSPATH = D:\IBMCPP\MSG\%N;$(TOOLKIT)\msg\N;
+
+vpath %.c .\H ..\samba\source\os2client .
+vpath %.h .\H ..\samba\source\os2client .
+
+NAME            =      ndpsmb
+
+INCLUDES        =      $(TOOLKIT)\H\LIBC;.\H;..\samba\source\os2client;.\rc
+
+#CFLAGS = -DDEBUG -Ge- -Gm+ -Ss -Sp1
+CFLAGS = -Ge- -Gm+ -Ss -Sp1
+LFLAGS = /NOE /MAP /ALIGN:16 /NODEBUG
+
+CC              =      icc $(CFLAGS) /I$(INCLUDES)
+LINK            =      icc /B "$(LFLAGS)" $(CFLAGS) $(LINKDEBUG) -Fe
+#LIBS           =      OS2386.LIB CPPRMS36.LIB
+LIBS            =      OS2386.LIB
+
+OBJS = $(NAME).obj
+
+all: $(NAME).dll $(NAME).hlp
+
+.c.obj:
+	$(CC) -c $(DLLCFLAGS) -Fo"$*.obj" $*.c
+
+$(NAME).dll: $(OBJS) $(NAME).def .\rc\rc.rc .\rc\rc.dlg .\rc\rc.h .\H\ndpl_rc.h makefile
+	$(LINK) $@ $(NAME).def $(LIBS) $(OBJS)
+	rc -i $(INCLUDES) .\rc\rc.rc $(NAME).dll
+	del .\rc\rc.res
+
+$(NAME).hlp: .\rc\rc.ipf .\rc\rc.h .\H\hmacros.h makefile
+	icc /I$(INCLUDES) /P /Pe .\rc\rc.ipf
+	ipfc rc.i $(NAME).hlp /COUNTRY=001 /CODEPAGE=850
+	del rc.i
+
+ndpsmb.obj: makefile .\H\ndextpl2.h .\H\ndfs.h ..\samba\source\os2client\smbcd.h ..\samba\source\os2client\smbwrp.h .\H\mydebug.h
+
+clean:
+	rm *.obj
+	rm *.map
+	rm *.dll
+	rm *.hlp
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.c	(revision 5)
@@ -0,0 +1,2483 @@
+#define NDPL_LARGEFILES
+#define INCL_LONGLONG
+#include <ndextpl2.h>
+#include <smbwrp.h>
+#include <smbcd.h>
+
+#define NULL ((void *)0)
+
+#include <mydebug.h>
+
+int StrLen(char * s)
+{
+	char * p;
+	if (!s)
+	{
+		return 0;
+	}
+	for (p = s; *p; p++);
+	return (p - s);
+}
+
+char * StrNCat(char *dst, const char *src, int count)
+{
+	int i;
+	if (!dst || !src || count <= 0)
+	{
+		return dst;
+	}
+	for (i = 0; dst[i]; i++);
+	for (;i < count && *src; i++, src++)
+	{
+		dst[i] = *src;
+	}
+	dst[i] = 0;
+	return dst;
+}
+
+char * StrNCpy(char *dst, const char *src, int count)
+{
+	if (!dst || !src || count <= 0)
+	{
+		return dst;
+	}
+	*dst = 0;
+	return StrNCat(dst, src, count);
+}
+
+char * StrCpy(char *dst, const char *src)
+{
+	char * p;
+	if (!dst || !src)
+	{
+		return dst;
+	}
+	p = dst;
+	while (*p++ = *src++);
+	return dst;
+}
+
+char * StrCat(char *dst, const char *src)
+{
+	int i;
+	if (!dst || !src)
+	{
+		return dst;
+	}
+	for (i = 0; dst[i]; i++);
+	for (; *src; i++, src++)
+	{
+		dst[i] = *src;
+	}
+	dst[i] = 0;
+	return dst;
+}
+
+void * MemCpy(void * dst, const void * src, int len)
+{
+	int i;
+	if (!src || !dst || len <= 0)
+	{
+		return dst;
+	}
+	for (i = 0; i < len; i++)
+	{
+		((char *)dst)[i] = ((char *)src)[i];
+	}
+	return dst;
+}
+
+void *MemSet(void *dst, char c, int len)
+{
+	int i;
+	if (!dst || len <= 0)
+	{
+		return dst;
+	}
+	for (i = 0; i < len; i++)
+	{
+		((char *)dst)[i] = c;
+	}
+	return dst;
+}
+
+/* uppercased type of resource */
+const char *NdpTypes[] =
+{
+	"SMBFS",
+	NULL
+}
+;
+
+/* Properties of supported resource types */
+
+/* Properties of resource */
+static const NDPROPERTYINFO smbProperties[] =
+{
+	{ND_PROP_STRING, 0, "WORKGROUP", ""},
+	{ND_PROP_STRING, 0, "SERVER", ""},
+	{ND_PROP_STRING, 0, "SHARE", ""},
+	{ND_PROP_STRING, 0, "USER", "guest"},
+	{ND_PROP_STRING, 0, "PASSWORD", ""},
+	{ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
+	{ ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
+	{ ND_PROP_ULONG, 0, "MEMLEN", "2"},
+	{ND_PROP_STRING, 0, "LOGFILE", ""},
+	{ ND_PROP_ULONG, 0, "LOGLEVEL", "0"},
+	{ ND_PROP_ULONG, 0, "EASUPPORT", "1"},
+	{ND_PROP_STRING, 0, NULL, NULL}
+};
+
+
+/* Exported array of properties */
+const NDPROPERTYINFO *NdpPropertiesInfo[] =
+{
+	smbProperties
+};
+
+
+static PLUGINHELPERTABLE2L *ph;
+static int ifL;
+
+int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
+{
+	int rc;
+	HPIPE pipe;
+	unsigned long action;
+	ph = pPHT;
+	ifL = 0;
+/*
+	if (ph->cb < sizeof (PLUGINHELPERTABLE2))
+	{
+		return ERROR_INVALID_FUNCTION;
+	}
+*/
+	if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
+	{
+		ifL = 1;
+	}
+	log("Working with %s bit fileio NDFS\n", ifL ? "64" : "32");
+	return NO_ERROR;
+}
+
+
+int APIENTRY NdpPluginFree (void)
+{
+	return NO_ERROR;
+}
+
+typedef struct _Resource
+{
+	/* NetDrive information */
+	NDPROPERTYHANDLE properties;	/* access handle for the properties */
+	int rootlevel;
+	unsigned long memlen;
+	unsigned long objany;
+	smbwrp_server srv;
+	char logfile[CCHMAXPATH + 1];
+	char loglevel;
+	int easupport;
+} Resource;
+
+typedef struct _Connection
+{
+	Resource *pRes;
+	HPIPE pipe;
+	char * mem;
+	int clientpid;
+	int rc;
+	smbwrp_server srv;
+	smbwrp_file file;
+} Connection;
+
+int openpipe(Resource * pRes, HPIPE * ppipe)
+{
+	HPIPE pipe = 0;
+	unsigned long rc = 0, action;
+
+	if (!pRes)
+	{
+		return ERROR_INVALID_PARAMETER;
+	}
+
+	rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
+	log("DosOpen1 rc %d\n", rc);
+	if (rc)
+	{
+		unsigned long sid = 0, pid = 0;
+		STARTDATA sd;
+		char params[CCHMAXPATH * 2] = {0};
+
+		MemSet(&sd, 0, sizeof(sd));
+		sd.Length = sizeof(sd);
+		sd.Related = SSF_RELATED_INDEPENDENT;
+		sd.FgBg = SSF_FGBG_BACK;
+		sd.PgmName = EXECNAME;
+		if (pRes->loglevel)
+		{
+			char level[2];
+			level[0] = pRes->loglevel + '0';
+			level[1] = 0;
+			StrNCat(params, " -d ", sizeof(params) - 1);
+			StrNCat(params, level, sizeof(params) - 1);
+		}
+		if (*pRes->logfile)
+		{
+			StrNCat(params, " -l ", sizeof(params) - 1);
+			StrNCat(params, pRes->logfile, sizeof(params) - 1);
+		}
+		log("params <%s>\n", params);
+		sd.PgmInputs = *params ? params : NULL;
+		sd.SessionType = SSF_TYPE_WINDOWABLEVIO;
+		rc = DosStartSession(&sd, &sid, &pid);
+		log("smbcd startsession pid %d sid %d rc %d\n", pid, sid, rc);
+		if (rc == ERROR_SMG_INVALID_CALL)
+		{
+			// ndfs started ndctl detached, so we have to use dosexecpgm
+			char failed[CCHMAXPATH + 1] = {0};
+			RESULTCODES res = {0};
+			char * p = params;
+			StrCpy(p, EXECNAME);
+			p += StrLen(p) + 1;
+			if (*pRes->logfile)
+			{
+				StrCpy(p, "-l ");
+				StrNCat(p, pRes->logfile, sizeof(params) - (p - (char *)params));
+				p += StrLen(p) + 1;
+				if (pRes->loglevel)
+				{
+					char level[2];
+					level[0] = pRes->loglevel + '0';
+					level[1] = 0;
+					StrCpy(p, "-d ");
+					StrNCat(p, level, sizeof(params) - (p - (char *)params));
+					p += StrLen(p) + 1;
+				}
+			}
+			else
+			{
+				StrCpy(p, "-q");
+				p += StrLen(p) + 1;
+			}
+			*p = 0;		
+			rc = DosExecPgm(failed, sizeof(failed), EXEC_BACKGROUND, params, NULL, &res, EXECNAME);
+			log("smbcd DosExecPgm codeTerminate %d codeResult %d rc %d\n", res.codeTerminate, res.codeResult, rc);
+		}
+		if (!rc)
+		{
+			DosSleep(500);
+			rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
+			log("DosOpen2 rc %d\n", rc);
+		}
+	}
+	if (!rc)
+	{
+		if (ppipe)
+		{
+			*ppipe = pipe;
+		}
+		else
+		{
+			DosClose(pipe);
+		}
+	}
+	return rc;
+}
+
+
+void getfindinfo(Connection * pConn, FILEFINDBUF3 * stat, smbwrp_fileinfo * finfo)
+{
+	char * name = ph->fsphStrRChr(finfo->fname, '\\');
+	if (name)
+	{
+		name++;
+	}
+	else
+	{
+		name = finfo->fname;
+	}
+	if (!*name)
+	{
+		name = pConn->srv.share_name;
+	}
+	StrNCpy(stat->achName, name, CCHMAXPATHCOMP - 1);
+	stat->cbFile = finfo->size;
+	stat->cbFileAlloc = stat->cbFile;
+	stat->oNextEntryOffset = 0ul;
+	stat->cchName = StrLen(stat->achName);
+	stat->attrFile = (finfo->attr & 0x37);
+
+    	ph->fsphUnixTimeToDosDate(finfo->mtime, &stat->fdateLastWrite, &stat->ftimeLastWrite);
+    	ph->fsphUnixTimeToDosDate(finfo->ctime, &stat->fdateCreation, &stat->ftimeCreation);
+    	ph->fsphUnixTimeToDosDate(finfo->atime, &stat->fdateLastAccess, &stat->ftimeLastAccess);
+}
+
+int getfindinfoL(Connection * pConn, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
+{
+	FILESTATUS3L stat = {0};
+	char * name = ph->fsphStrRChr(finfo->fname, '\\');
+	if (name)
+	{
+		name++;
+	}
+	else
+	{
+		name = finfo->fname;
+	}
+	if (!*name)
+	{
+		name = pConn->srv.share_name;
+	}
+	if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
+	{
+		return 0;
+	}
+
+	stat.cbFile = finfo->size;
+	stat.cbFileAlloc = stat.cbFile;
+	stat.attrFile = (finfo->attr & 0x37);
+
+    	ph->fsphUnixTimeToDosDate(finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
+    	ph->fsphUnixTimeToDosDate(finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
+    	ph->fsphUnixTimeToDosDate(finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
+
+	ph->fsphAddFile32L(plist, &stat, name, StrLen(name), finfo, sizeof(*finfo), 0);
+	return 1;
+}
+
+
+/* accept parameters in form
+ * [filename][;name=filename]
+ */
+int initResource (Resource *pRes)
+{
+	int rc = NO_ERROR;
+	unsigned long t;
+	const unsigned char * q = NULL;
+	HPIPE pipe;
+
+	pRes->memlen = 1 << 18;
+	pRes->rootlevel = 0;
+	*pRes->logfile = 0;
+	pRes->loglevel = 0;
+	pRes->easupport = 1;
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "WORKGROUP", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
+		pRes->rootlevel = 1;
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "SERVER", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
+		pRes->rootlevel = 2;
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "SHARE", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
+		pRes->rootlevel = 3;
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "USER", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "PASSWORD", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "MASTER", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
+	}
+
+	t = 0, q = NULL;
+	rc = ph->fsphQueryStringProperty (pRes->properties, "LOGFILE", &q, &t);
+	if (!rc && t && *q)
+	{
+		StrNCpy(pRes->logfile, q, sizeof(pRes->logfile) - 1);
+	}
+
+	t = 0;
+	rc = ph->fsphQueryUlongProperty (pRes->properties, "LOGLEVEL", &t);
+	if (!rc)
+	{
+		if (t > 9)
+		{
+			t = 9;
+			rc = ERROR_INVALID_PARAMETER;
+		}
+		pRes->loglevel = t;
+	}
+
+	t = 0;
+	rc = ph->fsphQueryUlongProperty (pRes->properties, "MASTERTYPE", &t);
+	if (!rc)
+	{
+		if (t > 1)
+		{
+			rc = ERROR_INVALID_PARAMETER;
+		}
+		else
+		{
+			pRes->srv.ifmastergroup = t;
+		}
+	}
+
+	t = 0;
+	rc = ph->fsphQueryUlongProperty (pRes->properties, "EASUPPORT", &t);
+	if (!rc)
+	{
+		if (t > 1)
+		{
+			rc = ERROR_INVALID_PARAMETER;
+		}
+		else
+		{
+			pRes->easupport = t;
+		}
+	}
+
+	t = 0;
+	rc = ph->fsphQueryUlongProperty (pRes->properties, "MEMLEN", &t);
+	if (!rc)
+	{
+		if (t <= (pRes->easupport ? 1 : 0) || t > 10)
+		{
+			rc = ERROR_INVALID_PARAMETER;
+		}
+		else
+		{
+			pRes->memlen = t * 65536;
+		}
+	}
+
+	return rc;
+}
+
+int checkconnection(Connection * pConn)
+{
+	int rc = NO_ERROR;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	if (!pConn)
+	{
+		return ERROR_INVALID_PARAMETER;
+	}
+	log("checkconnection pconnrc %d pipe %d\n", pConn->rc, pConn->pipe);
+	if (!pConn->rc)
+	{
+		unsigned long state = 0;
+		rc = DosQueryNPHState(pConn->pipe, &state);
+		log("DosQueryNPHstate(pConn->pipe) = %d (%08x)\n", pConn->rc, pConn->pipe, rc, state);
+		if (!rc)
+		{
+			return pConn->rc;
+		}
+	}
+	// there were error on pipe, reopen it and restore connection
+	if (pConn->pipe)
+	{
+		DosClose(pConn->pipe);
+		pConn->pipe = 0;
+	}
+	rc = openpipe(pConn->pRes, &pConn->pipe);
+	if (rc)
+	{
+		log("checkconnection openpipe %d\n", rc);
+		pConn->pipe = 0;
+		DosSleep(1000);
+		return ERROR_PIPE_NOT_CONNECTED;
+	}
+	do {
+		req.request = SMBREQ_INIT;
+		req.param = (char *)0xFFFFFFFF;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			break;
+		}
+		pConn->clientpid = resp.value & 0xFFFF;
+		// client daemon pid changed
+		pConn->rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
+		if (pConn->rc)
+		{
+			rc = pConn->rc;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
+		req.request = SMBREQ_CONNECT;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->srv);
+		req.length = req.paramlen;
+
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			break;
+		}
+		MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
+		rc = NO_ERROR;
+	} while (0);
+
+	if (pConn->rc && pConn->pipe)
+	{
+		DosClose(pConn->pipe);
+		pConn->pipe = 0;
+	}
+	return rc;
+}
+
+int iftestpath(char * path)
+{
+	char * p = path;
+	if (!path)
+	{
+		return 0;
+	}
+	while ((p = ph->fsphStrChr(p, 'A')) != NULL)
+	{
+		if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
+		{
+			return 1;
+		}
+		p++;
+	}
+	return 0;
+}
+
+int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
+{
+	int rootlevel;
+	int rc = NO_ERROR;
+	if (!pRes || !path || !result)
+	{
+		return ERROR_INVALID_PARAMETER;
+	}
+	// handle special case when someone wants to test support of LFN or smth similar
+	if (iftestpath(path))
+	{
+		StrCpy(result, "\\A.+,;=[].B");
+		return NO_ERROR;
+	}
+	rootlevel = pRes->rootlevel;
+	if (*path == '\\') path++;
+	if (rootlevel < 3)
+	{
+		char * p;
+		int newlevel = 0;
+		smbwrp_server * tmp = (smbwrp_server *)pConn->mem;
+		MemCpy(tmp, &pConn->srv, sizeof(pConn->srv));
+		if (rootlevel == 0)
+		{
+			p = ph->fsphStrChr(path, '\\');
+			if (!p)
+			{
+				p = path + StrLen(path);
+			}
+			if (StrLen(tmp->workgroup) != p - path
+				|| (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
+			{
+				StrNCpy(tmp->workgroup, path, p - path);
+				tmp->workgroup[p - path] = 0;
+				newlevel = 1;
+			}
+			path = *p == '\\' ? p + 1 : p;
+			rootlevel = 1;
+		}
+		if (rootlevel == 1) // root path starts from server name
+		{
+			p = ph->fsphStrChr(path, '\\');
+			if (!p)
+			{
+				p = path + StrLen(path);
+			}
+			if (StrLen(tmp->server_name) != p - path
+				|| (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
+			{
+				StrNCpy(tmp->server_name, path, p - path);
+				tmp->server_name[p - path] = 0;
+				newlevel = 1;
+			}
+			path = *p == '\\' ? p + 1 : p;
+			rootlevel = 2;
+		}
+		if (rootlevel == 2) // root path starts from share name
+		{
+			p = ph->fsphStrChr(path, '\\');
+			if (!p)
+			{
+				p = path + StrLen(path);
+			}
+			if (StrLen(tmp->share_name) != (p - path)
+				|| (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
+			{
+				StrNCpy(tmp->share_name, path, p - path);
+				tmp->share_name[p - path] = 0;
+				newlevel = 1;
+			}
+			path = *p == '\\' ? p + 1 : p;
+		}
+		if (newlevel)
+		{
+			// reconnect to server here
+			unsigned long action;
+			smb_request req = {0};
+			smb_response resp = {0};
+
+			req.request = SMBREQ_DISCONNECT;
+			req.param = pConn->mem;
+			req.length = 0;
+			req.paramlen = 0;
+
+			DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+
+			req.request = SMBREQ_CONNECT;
+			req.param = pConn->mem;
+			req.length = pRes->memlen;
+			req.paramlen = sizeof(pConn->srv);
+
+			rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+			if (rc || action < sizeof(resp) || resp.rc)
+			{
+				rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+				MemCpy(tmp, &pRes->srv, sizeof(pRes->srv));
+				DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+				// TODO: what to do if the reconnect will fail ?
+			}
+			else
+			{
+				MemCpy(&pConn->srv, tmp, sizeof(pConn->srv));
+			}
+		}
+	}
+	StrCpy(result, "\\");
+	StrNCat(result, path, CCHMAXPATH);
+	return rc;
+}
+
+int APIENTRY NdpFreeResource (HRESOURCE resource)
+{
+	Resource *pRes = (Resource *)resource;
+	MemSet(&pRes->srv, 0, sizeof(pRes->srv));
+	DosFreeMem(pRes);
+	log("NdpFreeResource %d\n", NO_ERROR);
+	return NO_ERROR;
+}
+
+
+int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
+{
+	int rc = NO_ERROR;
+	unsigned long objany = OBJ_ANY;
+	Resource *pRes = NULL;
+	/* since we support only 1 type of resources we do not need */
+	/* to check what the found type really is */
+	rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE | objany);
+	if (rc == ERROR_INVALID_PARAMETER)
+	{
+		objany = 0;
+		rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE);
+	}
+	if (!rc && pRes == NULL)
+	{
+		rc = ERROR_NOT_ENOUGH_MEMORY;
+	}
+	if (!rc)
+	{
+		MemSet(pRes, 0, sizeof(Resource));
+		pRes->properties = properties;
+		pRes->objany = objany;
+		rc = initResource (pRes);
+		if (rc == NO_ERROR)
+		{
+			*presource = (HRESOURCE)pRes;
+		}
+		else
+		{
+			NdpFreeResource((HRESOURCE)pRes);
+		}
+	}
+	log("NdpMountResource %d\n", rc);
+	return rc;
+}
+
+int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
+{
+	int rc;
+	Resource * pRes = (Resource *)resource;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	Connection *pConn = NULL;
+
+	log("NdpCreateConnection in\n");
+
+	rc = DosAllocMem((void **)&pConn, sizeof(Connection), PAG_COMMIT | PAG_READ | PAG_WRITE | pRes->objany);
+	if (!rc && pConn == NULL)
+	{
+		rc =  ERROR_NOT_ENOUGH_MEMORY;
+	}
+	if (rc)
+	{
+		log("NdpCreateConnection %d\n", rc);
+		return rc;
+	}
+	MemSet(pConn, 0, sizeof(Connection));
+	pConn->pRes = pRes;
+	pConn->file.fd = -1;
+
+	do {
+		rc = openpipe(pRes, &pConn->pipe);
+		if (rc)
+		{
+			pConn->pipe = 0;
+			break;
+		}
+
+		req.request = SMBREQ_INIT;
+		req.param = (char *)0xFFFFFFFF;
+		rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (rc || action < sizeof(resp) || resp.rc)
+		{
+			return rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		pConn->clientpid = resp.value & 0xFFFF;
+
+		rc = DosAllocSharedMem((PPVOID)&pConn->mem, NULL, pRes->memlen, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | pRes->objany);
+		if (rc)
+		{
+			break;
+		}
+		rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
+		if (rc)
+		{
+			break;
+		}
+
+		MemCpy(pConn->mem, &pRes->srv, sizeof(pRes->srv));
+		req.request = SMBREQ_CONNECT;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->srv);
+		req.length = req.paramlen;
+
+		rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
+		}
+	} while (0);
+	if (rc)
+	{
+		if (pConn->mem)
+		{
+			DosFreeMem(pConn->mem);
+		}
+		if (pConn->pipe)
+		{
+			DosClose(pConn->pipe);
+		}
+		MemSet(pConn, 0, sizeof(*pConn));
+		DosFreeMem(pConn);
+		pConn = NULL;
+	}
+
+	*pconn = (HCONNECTION)pConn;
+	log("NdpCreateConnection %d %d\n", rc, resp.rc);
+	return rc;
+}
+
+
+int APIENTRY NdpFreeConnection (HCONNECTION conn)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+
+	log("NdpFreeConnection in\n");
+	if (pConn->mem)
+	{
+		smb_request req = {0};
+		smb_response resp = {0};
+		unsigned long action;
+		if (pConn->file.fd >= 0)
+		{
+			MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+			req.request = SMBREQ_CLOSE;
+			req.param = pConn->mem;
+			req.length = sizeof(pConn->file);
+			req.paramlen = sizeof(pConn->file);
+
+			DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+			pConn->file.fd = -1;
+		}
+
+		req.request = SMBREQ_DISCONNECT;
+		req.param = pConn->mem;
+		req.length = 0;
+		req.paramlen = 0;
+
+		DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+
+		DosFreeMem(pConn->mem);
+		DosClose(pConn->pipe);
+		MemSet(pConn, 0, sizeof(*pConn));
+	}
+
+	DosFreeMem(pConn);
+	log("NdpFreeConnection %d\n", NO_ERROR);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
+{
+	Resource *pRes = (Resource *)resource;
+	Resource *pRes2 = (Resource *)resource2;
+	int rc = ND_RSRC_DIFFERENT;
+
+	log("NdpRsrcCompare in\n");
+
+	if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
+		&& ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
+		&& ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
+		&& ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
+	{
+		// resources are equal
+		rc = ND_RSRC_EQUAL;
+	}
+
+	log("NdpRsrcCompare %d\n", rc);
+
+	return rc;
+}
+
+int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
+{
+	// do nothing
+	log("NdpRsrcUpdate %d\n", NO_ERROR);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
+{
+	Resource *pRes = (Resource *)resource;
+	int rc = NO_ERROR;
+	char s[4096];
+
+	log("NdpRsrcQueryInfo in\n");
+
+	switch (pRes->rootlevel)
+	{
+		case 0:
+		{
+			ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
+		} break;
+		case 1:
+		{
+			ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
+		} break;
+		case 2:
+		{
+			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);
+		} break;
+		default:
+		{
+			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);
+		} break;
+	}
+	*poutlen = StrLen(s) + 1;
+	if (*poutlen > insize)
+	{
+		rc = ERROR_BUFFER_OVERFLOW;
+	}
+	else
+	{
+		MemCpy(pdata, s, *poutlen);
+	}
+
+	log("NdpRsrcQueryInfo %d\n", rc);
+
+	return rc;
+}
+
+int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
+{
+	ULONG ulDummy = 0;
+	/* just return the resource info string */
+	return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
+}
+
+int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
+{
+	int rc = NO_ERROR, rc1;
+
+	Connection *pConn = 0;
+	smb_request req = {0};
+	smb_response resp = {0};
+	unsigned long action = 0;
+
+	log("NdpRsrcQueryFSAllocate %08x\n", pfsa);
+
+	if (!pfsa)
+	{
+		return NO_ERROR;
+	}
+
+
+	rc = NdpCreateConnection (resource, (HCONNECTION *)&pConn);
+	if (rc) 
+	{
+		log("NdpCreateConnection failed rc=%d\n", rc);	
+		pfsa->cSectorUnit = 1;
+		pfsa->cUnit = 123456;
+		pfsa->cUnitAvail = 123456;
+		pfsa->cbSector = 2048;
+		return rc;
+	}
+
+	MemSet(pConn->mem, 0, sizeof(FSALLOCATE));
+	req.request = SMBREQ_DSKATTR;
+	req.param = pConn->mem;
+	req.paramlen = sizeof(FSALLOCATE);
+	req.length = req.paramlen;
+
+	rc = DosTransactNPipe( pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+	if (rc || action < sizeof(resp) || resp.rc)
+	{
+		pfsa->cSectorUnit = 1;
+		pfsa->cUnit = 123456;
+		pfsa->cUnitAvail = 123456;
+		pfsa->cbSector = 2048;
+		rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+	}
+	else
+	{
+		FSALLOCATE * fsa = (FSALLOCATE *)pConn->mem;
+		pfsa->cSectorUnit = fsa->cSectorUnit;
+		pfsa->cUnit = fsa->cUnit;
+		pfsa->cUnitAvail = fsa->cUnitAvail;
+		pfsa->cbSector = fsa->cbSector;
+	}
+
+	rc1 = NdpFreeConnection((HCONNECTION)pConn);
+
+	log("NdpRsrcQueryFSAllocate %d/%d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, resp.rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
+	return rc;
+}
+
+int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = NO_ERROR, count = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	char *mask = "*";
+	char dir[CCHMAXPATH+1] = {0};
+	char path[CCHMAXPATH+1] = {0};
+	char fullname[CCHMAXPATH+1] = {0};
+	smbwrp_fileinfo * data;
+	NDPATHELEMENT *pel = ph->fsphNameElem(0);
+
+	log("NdpFindStart in\n");
+	do
+	{
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(dir, szPath, sizeof(dir) - 1);
+		if (pel)
+		{
+			mask = pel->name;
+			dir[StrLen(szPath) - pel->length] = 0;
+		}
+		action = StrLen(dir) - 1;
+		if (dir[action] == '\\')
+		{
+			dir[action] = 0;
+		}
+		rc = pathparser(pRes, pConn, dir, path);
+		if (rc)
+		{
+			break;
+		}
+		action = StrLen(path) - 1;
+		if (path[action] != '\\')
+		{
+			StrNCat(path, "\\", sizeof(path) - 1);
+		}
+		StrCpy(dir, path);
+		StrNCat(path, mask, sizeof(path) - 1);
+
+		MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
+		StrCpy(pConn->mem + sizeof(pConn->srv), path);
+		req.request = SMBREQ_FILELIST;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->srv) + CCHMAXPATH + 1;
+		req.length = pRes->memlen;
+		data = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->srv) + CCHMAXPATH + 1);
+
+		do {
+			int i;
+			pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+			if (pConn->rc || action < sizeof(resp)
+				|| (resp.rc && resp.rc != ERROR_MORE_DATA))
+			{
+				rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+				break;
+			}
+log("NdpFindStart %d %d %d\n", pConn->rc, resp.rc, resp.length / sizeof(smbwrp_fileinfo));
+			if (ifL)
+			{
+				for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
+				{
+					smbwrp_fileinfo * finfo = data + i;
+log("NdpFindStart found <%s> %d\n", finfo->fname, finfo->easize);
+					StrCpy(fullname, dir);
+					StrCat(fullname, finfo->fname);
+					StrCpy(finfo->fname, fullname);
+					count += getfindinfoL(pConn, plist, finfo, ulAttribute, mask);
+				}
+			}
+			else
+			{
+				FILEFINDBUF3 buf = {0};
+				for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
+				{
+					smbwrp_fileinfo * finfo = data + i;
+					getfindinfo(pConn, &buf, finfo);
+		
+					if (ph->fsphAttrMatch(ulAttribute, buf.attrFile)
+						&& ph->fsphWildMatch(mask, buf.achName, ND_IGNORE_CASE))
+					{
+						StrCpy(fullname, dir);
+						StrCat(fullname, finfo->fname);
+						StrCpy(finfo->fname, fullname);
+						ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
+						count++;
+					}
+				}
+			}
+		} while (resp.rc == ERROR_MORE_DATA);
+	} while (0);
+
+	log("NdpFindStart <%s> (%s) cnt %d %d %d\n", szPath, path, count, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpQueryInfo in <%s>\n", szPath);
+
+	do {
+		if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
+		{
+			rc = ERROR_FILE_NOT_FOUND;
+			break;
+		}
+
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szPath, path);
+		switch (rc)
+		{
+			case NO_ERROR :
+			case ERROR_FILE_NOT_FOUND:
+			case ERROR_PATH_NOT_FOUND:
+			case ERROR_ACCESS_DENIED:
+			case ERROR_INVALID_PARAMETER:
+			{
+				break;
+			}
+			default :
+			{	
+				rc = ERROR_PATH_NOT_FOUND;
+			}
+		}
+		if (rc)
+		{
+			break;
+		}
+		StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
+		req.request = SMBREQ_GETINFO;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(*finfo);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			switch (resp.rc)
+			{
+				case NO_ERROR :
+				case ERROR_FILE_NOT_FOUND:
+				case ERROR_PATH_NOT_FOUND:
+				case ERROR_ACCESS_DENIED:
+				case ERROR_INVALID_PARAMETER:
+					break;
+				default :
+				{
+					resp.rc = ERROR_PATH_NOT_FOUND;
+				}
+			}
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			finfo->easize = -1;
+			if (ifL)
+			{
+				getfindinfoL(pConn, plist, finfo, 0, NULL);
+			}
+			else
+			{
+				int trc;
+				FILEFINDBUF3 buf = {0};
+				getfindinfo(pConn, &buf, finfo);
+				trc = ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
+				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);
+			}
+		}
+		if (rc == ERROR_FILE_NOT_FOUND)
+		{
+			// now try the upper path
+			char * p = ph->fsphStrChr(finfo->fname, '\\');
+			if (p && p > finfo->fname)
+			{
+				*p = 0;
+				rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+				if (pConn->rc || action < sizeof(resp) || resp.rc)
+				{	
+					rc = pConn->rc ? pConn->rc : (resp.rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER);
+				}
+			}
+		}
+	} while (0);
+
+	log("NdpQueryInfo <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
+{
+//	log("NdpDeletePathInfo %d\n", 0);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
+{
+	log("NdpRefresh <%s> %d\n", path, 0);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
+{
+    // The plugin do not have to deallocate anything
+    // because resource data did not contain any pointers
+    // to plugins data.
+    // Data stored by fsphSetResourceData will be
+    // deallocated by NetDrive.
+
+	log("NdpDicardresourceData %d\n", 0);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpSetPathInfo in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szPathName, path);
+		if (rc)
+		{
+			break;
+		}
+
+		MemSet(finfo, 0, sizeof(*finfo));
+
+		StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
+		ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(finfo->mtime));
+		if (ifL)
+		{
+			finfo->attr = pfi->stat.attrFile & 0x37;
+		}
+		else
+		{
+			FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
+			finfo->attr = stat->attrFile & 0x37;
+		}
+		req.request = SMBREQ_SETINFO;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(*finfo);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpSetPathInfo <%s> (%s) %d %d\n", szPathName, path, rc, pConn->rc);
+	return rc;
+}
+
+int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
+{
+	int rc = 0;
+	FEA * pfea;
+	FEA * pfeadest;
+	unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
+
+	size = pFEASrc->cbList;
+	pfea = pFEASrc->list;
+	pfeadest = pFEAList->list;
+	dsize = pFEAList->cbList;
+//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
+	while (done < size)
+	{
+		char * name = (char *)(pfea + 1);
+		int insert = 1;
+		if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
+		{
+			GEA * pgea = pGEAList->list;
+			unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
+			insert = 0;
+			while (done < size)
+			{
+//log("comp <%s> <%s>\n", name, pgea->szName);
+				if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
+				{
+					insert = 1;
+					break;
+				}
+				done += pgea->cbName + 2;
+				pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
+			}
+		}
+		if (insert)
+		{
+			ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
+			if (ddone <= dsize)
+			{
+				pfeadest->cbName = pfea->cbName;
+				pfeadest->cbValue = pfea->cbValue;
+				pfeadest->fEA = 0;
+				StrCpy((char *)(pfeadest + 1), name);
+				MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
+				pfeadest = (FEA *)((char *)pFEAList + ddone);
+			}
+		}
+		done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
+//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);
+		pfea = (FEA *)((char *)pFEASrc + done);
+	}
+	pFEAList->cbList = ddone;
+	if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
+	{
+		rc = ERROR_BUFFER_OVERFLOW;
+	}
+	log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
+	return rc;
+}
+
+int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	char * path = NULL;
+	FEALIST * pFEASrc;
+	NDDATABUF fdata = {0};
+
+	if (!pfi || !pfi->pszName || !pFEAList)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+
+	rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
+	if (rc || !fdata.ulSize || !fdata.pData)
+	{
+		log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	path = (char *)fdata.pData;
+
+	log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_LISTEA;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = pRes->memlen - req.paramlen;
+		pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			switch (rc)
+			{
+				case ERROR_FILE_NOT_FOUND :
+				case ERROR_PATH_NOT_FOUND :
+				{
+					pFEAList->cbList = sizeof(pFEAList->cbList);
+					rc = NO_ERROR;
+				} break;
+				case ERROR_BUFFER_OVERFLOW :
+				{
+					pFEAList->cbList = pFEASrc->cbList;
+				} break;
+				default :
+				{
+					rc = ERROR_EAS_NOT_SUPPORTED;
+				}
+			}
+		}
+		else
+		{
+			rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
+		}
+	} while (0);
+	log("NdpEAQuery <%s> %d %d %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList, pConn->rc, resp.rc);
+	return rc;
+}
+
+int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	smb_request req = {0};
+	smb_response resp = {0};
+	char * path;
+	unsigned long action;
+	NDDATABUF fdata = {0};
+
+	log("NdpEASet in\n");
+
+	if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+
+	if (pFEAList->cbList > pRes->memlen)
+	{
+		return ERROR_NOT_ENOUGH_MEMORY;
+	}
+
+	rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
+	if (rc || !fdata.ulSize || !fdata.pData)
+	{
+		log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	path = (char *)fdata.pData;
+
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		MemCpy(pConn->mem + CCHMAXPATH + 1, pFEAList, pFEAList->cbList);
+		req.request = SMBREQ_SETEA;
+		req.param = pConn->mem;
+		req.paramlen = pFEAList->cbList + CCHMAXPATH + 1;
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpEASet %d\n", rc);
+	return rc;
+}
+
+int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	char * path = NULL;
+	FEALIST * pfealist;
+	NDDATABUF fdata = {0};
+	int easize;
+
+	if (!pfi || !pulEASize)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+
+	rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
+	if (rc || !fdata.ulSize || !fdata.pData)
+	{
+		log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	easize = ((smbwrp_fileinfo *)fdata.pData)->easize;
+	((smbwrp_fileinfo *)fdata.pData)->easize = -1;
+	path = ((smbwrp_fileinfo *)fdata.pData)->fname;
+	if (easize >= 0)
+	{
+		*pulEASize = easize;
+		log("NdpEASize <%s> cached %d\n", path, easize);
+		return NO_ERROR;
+	}
+
+	log("NdpEASize in <%s> \n", path);
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_LISTEA;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = pRes->memlen - req.paramlen;
+		pfealist = (FEALIST *)(pConn->mem + req.paramlen);
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			switch (rc)
+			{
+				case ERROR_FILE_NOT_FOUND :
+				case ERROR_PATH_NOT_FOUND :
+				{
+					pfealist->cbList = sizeof(pfealist->cbList);
+				} /* Fall through */
+				case ERROR_BUFFER_OVERFLOW :
+				{
+					rc = NO_ERROR;
+				} break;
+				default :
+				{
+					rc = ERROR_EAS_NOT_SUPPORTED;
+				}
+			}
+		}
+		*pulEASize = pfealist->cbList;
+	} while (0);
+	log("NdpEASize <%s> %d %d %d %d\n", pfi->pszName, *pulEASize, rc, pConn->rc, resp.rc);
+	return rc;
+}
+
+int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	int rc = 0;
+	unsigned long action;
+	char path[CCHMAXPATH+1] = {0};
+	
+	log("NdpSetCurrentDir in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szPath, path);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_CHDIR;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpSetCurrentDir <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
+{
+	log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
+	return ERROR_CANNOT_COPY;
+}
+
+int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
+{
+	log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
+	return ERROR_CANNOT_COPY;
+}
+
+int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	int rc = 0;
+	unsigned long action;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpForceDelete in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szFile, path);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_UNLINK;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpForceDelete <%s> (%s) %d %d\n", szFile, path, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	int rc = 0;
+	unsigned long action;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpCreateDir in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szDirName, path);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_MKDIR;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpCreateDir <%s> (%s) %d %d\n", szDirName, path, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	int rc = 0;
+	unsigned long action;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpDeleteDir in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szDir, path);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->mem, path, CCHMAXPATH);
+		req.request = SMBREQ_RMDIR;
+		req.param = pConn->mem;
+		req.paramlen = CCHMAXPATH + 1;
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpDeleteDir <%s> (%s) %d %d\n", szDir, path, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	int rc = 0;
+	unsigned long action;
+	char src[CCHMAXPATH+1] = {0};
+	int l1, l2;
+	char * p = szDst;
+
+	log("NdpMove in\n");
+	do
+	{
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szSrc, src);
+		if (rc)
+		{
+			break;
+		}
+		l1 = StrLen(szSrc);
+		l2 = StrLen(src);
+		if (l1 > l2)
+		{
+			if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
+			{
+				// the file moved accross different shares or servers or workgroups
+				rc = ERROR_WRITE_PROTECT;
+				break;
+			}
+			p = szDst + l1 - l2 + 1;
+		}
+		StrNCpy(pConn->mem, src, CCHMAXPATH);
+		pConn->mem[CCHMAXPATH + 1] = '\\';
+		StrNCpy(pConn->mem + CCHMAXPATH + 2, p, CCHMAXPATH - 1);
+		req.request = SMBREQ_RENAME;
+		req.param = pConn->mem;
+		req.paramlen = 2 * (CCHMAXPATH + 1);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpMove <%s> -> <%s> (%s) %d %d\n", szSrc, szDst, src, rc, pConn->rc);
+
+	return rc;
+}
+
+int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
+{
+	log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
+	return ERROR_WRITE_PROTECT;
+}
+
+
+int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
+{
+	return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
+}
+
+int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
+{
+	return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
+}
+
+int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
+{
+	Resource *pRes = pConn->pRes;
+	smb_request req = {0};
+	smb_response resp = {0};
+	unsigned long action;
+	int rc = 0;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("smbopen in %d\n", pConn->file.fd);
+	do {
+		if (pConn->file.fd > 0)
+		{
+			rc = ERROR_TOO_MANY_OPEN_FILES;
+			break;
+		}
+
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szFileName, path);
+		if (rc)
+		{
+			break;
+		}
+
+		StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
+		StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
+		flags |= O_BINARY;
+		switch (ulOpenMode & 3)
+		{
+			case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
+			case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
+			case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
+			default : flags |= O_RDWR;
+		}
+		pConn->file.openmode = flags;
+		pConn->file.openattr = ulAttribute & 0x37;
+		pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_OPEN;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+		}
+	} while (0);
+	log("smbopen <%s> (%s) %08x %08x %08x %d %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->rc, pConn->file.fd);
+	if (!rc && pFEAList)
+	{
+		int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
+		log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
+	}
+
+	return rc;
+}
+
+int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
+{
+	return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
+}
+
+int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
+{
+	return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
+}
+
+int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
+{
+//	return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
+	return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
+}
+
+int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
+{
+	return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
+}
+
+int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
+{
+	if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
+	return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
+}
+
+int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
+	char path[CCHMAXPATH+1] = {0};
+
+	log("NdpSetFileAttribute in\n");
+	do {
+		rc = checkconnection(pConn);
+		if (rc)
+		{
+			break;
+		}
+
+		rc = pathparser(pRes, pConn, szFileName, path);
+		if (rc)
+		{
+			break;
+		}
+
+		MemSet(finfo, 0, sizeof(*finfo));
+
+		StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
+		finfo->attr = usAttr & 0x37;
+		req.request = SMBREQ_SETINFO;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(*finfo);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpSetFileAttribute <%s> (%s) %04x %d %d\n", szFileName, path, usAttr, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpFlush (HRESOURCE resource)
+{
+	log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
+	return ERROR_NOT_SUPPORTED;
+}
+
+int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
+{
+	log("NdpIOCTL <%s> %d %d\n", path, function, ERROR_NOT_SUPPORTED);
+	return ERROR_NOT_SUPPORTED;
+}
+
+int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	FILEFINDBUF3 buf;
+	smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->file));
+
+	log("NdpFileQueryInfo in\n");
+	do {
+		if (pConn->file.fd < 0 || !*pConn->file.fname)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		StrNCpy(finfo->fname, pConn->file.fname, sizeof(finfo->fname) - 1);
+		req.request = SMBREQ_FGETINFO;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+		req.length = req.paramlen + sizeof(*finfo);
+		rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			finfo->easize = -1;
+			if (ifL)
+			{
+				getfindinfoL(pConn, plist, finfo, 0, NULL);
+			}
+			else
+			{
+				getfindinfo(pConn, &buf, finfo);
+				ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
+			}
+		}
+	} while (0);
+	log("NdpFileQueryInfo <%s> %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc, pConn->rc);
+
+	return rc;
+}
+
+int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	FEALIST * pFEASrc;
+
+	if (!pFEAList)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+
+	log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_FLISTEA;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+		req.length = pRes->memlen - req.paramlen;
+		pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			switch (rc)
+			{
+				case ERROR_FILE_NOT_FOUND :
+				case ERROR_PATH_NOT_FOUND :
+				{
+					pFEAList->cbList = sizeof(pFEAList->cbList);
+					rc = NO_ERROR;
+				} break;
+				case ERROR_BUFFER_OVERFLOW :
+				{
+					pFEAList->cbList = pFEASrc->cbList;
+				} break;
+				default :
+				{
+					rc = ERROR_EAS_NOT_SUPPORTED;
+				}
+			}
+		}
+		else
+		{
+			rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
+		}
+	} while (0);
+	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);
+	return rc;
+}
+
+int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	smb_request req = {0};
+	smb_response resp = {0};
+	unsigned long action;
+
+	log("NdpFileEASet in\n");
+
+	if (!pFEAList || pFEAList->cbList <= sizeof(long))
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (pFEAList->cbList > pRes->memlen)
+	{
+		return ERROR_NOT_ENOUGH_MEMORY;
+	}
+
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		MemCpy(pConn->mem + sizeof(pConn->file), pFEAList, pFEAList->cbList);
+		req.request = SMBREQ_FSETEA;
+		req.param = pConn->mem;
+		req.paramlen = pFEAList->cbList + sizeof(pConn->file);
+		req.length = req.paramlen;
+
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+	} while (0);
+	log("NdpFileEASet %d\n", rc);
+	return rc;
+}
+
+int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+	char path[CCHMAXPATH+1] = {0};
+	FEALIST * pfealist;
+
+	if (!pulEASize)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+	if (!pRes->easupport)
+	{
+		return ERROR_EAS_NOT_SUPPORTED;
+	}
+
+	log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_FLISTEA;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+		req.length = pRes->memlen - req.paramlen;
+		pfealist = (FEALIST *)(pConn->mem + req.paramlen);
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+			switch (rc)
+			{
+				case ERROR_FILE_NOT_FOUND :
+				case ERROR_PATH_NOT_FOUND :
+				{
+					pfealist->cbList = sizeof(pfealist->cbList);
+				} /* Fall through */
+				case ERROR_BUFFER_OVERFLOW :
+				{
+					rc = NO_ERROR;
+				} break;
+				default :
+				{
+					rc = ERROR_EAS_NOT_SUPPORTED;
+				}
+			}
+		}
+		*pulEASize = pfealist->cbList;
+	} while (0);
+	log("NdpFileEASize %d %d %d %d\n", *pulEASize, rc, pConn->rc, resp.rc);
+	return rc;
+}
+
+int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action, attrFile;
+	smb_request req = {0};
+	smb_response resp = {0};
+	smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
+
+	log("NdpFileSetInfo in\n");
+	do {
+		if (pConn->file.fd < 0 || !*pConn->file.fname)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+		if (ifL)
+		{
+			attrFile = pfi->stat.attrFile;
+		}
+		else
+		{
+			FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
+			attrFile = stat->attrFile;
+		}
+		// deferred setinfo - on closing the file
+		pConn->file.openattr = attrFile;
+		ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(pConn->file.mtime));
+	} while (0);
+	log("NdpFileSetInfo <%s> %08x %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc, pConn->rc);
+	return NO_ERROR;
+}
+
+int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+
+	log("NdpFileSetFilePtrl in\n");
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		*(unsigned long *)(pConn->mem + sizeof(pConn->file)) = ulMethod;
+		*(long long *)(pConn->mem + sizeof(pConn->file) + sizeof(long)) = llOffset;
+		req.request = SMBREQ_LSEEK;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file) + sizeof(long) + sizeof(long long);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+			*pllActual = pConn->file.offset;
+		}
+	} while (0);
+	log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc, pConn->rc);
+
+	return rc;
+}
+
+int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
+{
+	LONGLONG llActual;
+	int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
+	*pulActual = llActual & 0xFFFFFFFF;
+	log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
+	return rc;
+}
+
+int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+
+	log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
+
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_CLOSE;
+		req.param = pConn->mem;
+		req.length = pRes->memlen;
+		req.paramlen = sizeof(pConn->file);
+		req.length = req.paramlen;
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+		}
+	} while (0);
+	log("NdpFileClose %d %d %d\n", pConn->file.fd, rc, pConn->rc);
+	pConn->file.fd = -1;
+	return rc;
+}
+
+int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
+{
+	log("NdpFileCommit %d\n", NO_ERROR);
+	return NO_ERROR;
+}
+
+
+int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
+{
+	int rc = NdpFileNewSizeL(conn, handle, ulLen);
+	log("NdpFileNewSize %ld %d\n", ulLen, rc);
+	return rc;
+}
+
+int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+
+	log("NdpFileNewSizeL in\n");
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		*(long long *)(pConn->mem + sizeof(pConn->file)) = llLen;
+
+		req.request = SMBREQ_NEWSIZE;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file) + sizeof(long long);
+		req.length = req.paramlen;
+
+		pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+		if (pConn->rc || action < sizeof(resp) || resp.rc)
+		{
+			rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+		}
+		else
+		{
+			MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+		}
+	} while (0);
+	log("NdpFileNewSizeL <%s> %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc, pConn->rc);
+	return rc;
+}
+
+int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long done = 0;
+	unsigned long onedone;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+
+	log("NdpFileRead in\n");
+//	log("NdpFileRead <%s> %lu\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead);
+
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+	
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_READ;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+
+		while (done < ulRead)
+		{
+			req.length = req.paramlen + (pRes->memlen - req.paramlen < (ulRead - done) ? pRes->memlen - req.paramlen : (ulRead - done));
+	
+			pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+			if (pConn->rc || action < sizeof(resp) || resp.rc)
+			{
+				rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+				break;
+			}
+			if (resp.value == 0)
+			{
+				break;
+			}
+			onedone = resp.value > req.length ? req.length : resp.value;
+			MemCpy((char *)pBuffer + done, pConn->mem + sizeof(pConn->file), onedone);
+			done += onedone;
+		}
+		MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+		*pulActual = done;
+	} while (0);
+	log("NdpFileRead <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc, pConn->rc);
+
+	return rc;
+}
+
+int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
+{
+	Connection *pConn = (Connection *)conn;
+	Resource *pRes = pConn->pRes;
+	int rc = 0;
+	unsigned long done = 0;
+	unsigned long onedone;
+	unsigned long action;
+	smb_request req = {0};
+	smb_response resp = {0};
+
+	log("NdpFileWrite in\n");
+	do {
+		if (pConn->file.fd < 0)
+		{
+			rc = ERROR_INVALID_HANDLE;
+			break;
+		}
+		if (pConn->rc)
+		{
+			rc = ERROR_PIPE_NOT_CONNECTED;
+			break;
+		}
+	
+		MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
+		req.request = SMBREQ_WRITE;
+		req.param = pConn->mem;
+		req.paramlen = sizeof(pConn->file);
+
+		while (done < ulWrite)
+		{
+			req.length = pRes->memlen - req.paramlen < (ulWrite - done) ? pRes->memlen - req.paramlen : (ulWrite - done);
+			MemCpy(pConn->mem + sizeof(pConn->file), (char *)pBuffer + done, req.length);
+			req.length += req.paramlen;
+
+			pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
+			if (pConn->rc || action < sizeof(resp) || resp.rc)
+			{
+				rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
+				break;
+			}
+			done += resp.value & 0xFFFFFFFF;
+			if (resp.value < req.length)
+			{
+				break;
+			}
+		}
+		MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
+		*pulActual = done;
+	} while (0);
+	log("NdpFileWrite <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc, pConn->rc);
+
+	return rc;
+}
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.def
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.def	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.def	(revision 5)
@@ -0,0 +1,66 @@
+LIBRARY NDPSMB INITINSTANCE TERMINSTANCE
+PROTMODE
+DESCRIPTION '@#NICKK:2.0#@NDPSMB - SMBFS NetDrive External Plugin'
+DATA MULTIPLE NONSHARED
+STACKSIZE 65536
+EXPORTS
+    NdpTypes
+    NdpPropertiesInfo
+    NdpPluginLoad
+    NdpPluginFree
+
+    NdpMountResource
+    NdpFreeResource
+    NdpCreateConnection
+    NdpFreeConnection
+
+    NdpRsrcCompare
+    NdpRsrcUpdate
+    
+    NdpRsrcQueryInfo
+    NdpRsrcQueryFSAttach
+    NdpRsrcQueryFSAllocate
+
+    NdpQueryPathInfo
+    NdpDeletePathInfo
+    NdpDiscardResourceData
+    NdpRefresh
+    NdpSetPathInfo
+    NdpEAQuery
+    NdpEASet
+    NdpEASize
+    NdpSetCurrentDir
+    NdpCopy
+    NdpCopy2
+    NdpForceDelete
+    NdpCreateDir
+    NdpFindStart
+    NdpMove
+    NdpMove2
+    NdpChangeCase
+    NdpRename
+    NdpOpenExisting
+    NdpOpenReplace
+    NdpOpenCreate
+    NdpDeleteDir
+    NdpSetFileAttribute
+
+    NdpFlush
+    NdpIOCTL
+
+    NdpFileQueryInfo
+    NdpFileEAQuery
+    NdpFileEASet
+    NdpFileEASize
+    NdpFileSetInfo
+    NdpFileSetFilePtr
+    NdpFileClose
+    NdpFileCommit
+    NdpFileNewSize
+    NdpFileRead
+    NdpFileWrite
+
+    NdpOpenReplaceL
+    NdpOpenCreateL
+    NdpFileSetFilePtrL
+    NdpFileNewSizeL
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.ndp
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.ndp	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.ndp	(revision 5)
@@ -0,0 +1,6 @@
+title = "SMB FS"
+name = ndpsmb
+file = ndpsmb.dll
+file = ndpsmb.hlp
+file = ndpsmb.ndp
+file = smbcd.exe|..\smbcd.exe
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.c	(revision 5)
@@ -0,0 +1,147 @@
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+//_SMB_H
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+#include <InnoTekLIBC/backend.h>
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#include "local.h"
+#include "xfile.h"
+#include "pstring.h"
+#include "debug.h"
+
+APIRET (APIENTRY * xDosPerfSysCall)(ULONG ulCommand, ULONG ulParm1, ULONG ulParm2, ULONG ulParm3) = NULL;
+APIRET (APIENTRY * xDosQuerySysState)(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz) = NULL;
+HMODULE doscalls = 0;
+
+int os2_init(void)
+{
+	HMODULE dllhandle;
+	int rc = 0;
+	char failname[CCHMAXPATH+1];
+	if (doscalls == 0) 
+	{
+		rc = DosLoadModule(failname, sizeof(failname), "DOSCALL1", &doscalls);
+		if (rc)
+		{
+			DEBUG(0,("Cant load DOSCALL1: %s (%d)\n", failname, rc));
+			return rc;
+		}
+		rc = DosQueryProcAddr(doscalls, 976, NULL, (PFN *)&xDosPerfSysCall);
+		if (rc)
+		{
+			DEBUG(0,("Cant load xDosPerfSysCall (%d)\n", rc));
+			xDosPerfSysCall = NULL;
+		}
+		rc = DosQueryProcAddr(doscalls, 368, NULL, (PFN *)&xDosQuerySysState);
+		if (rc)
+		{
+			DEBUG(0,("Cant load xDosQuerySysState (%d)\n", rc));
+			xDosQuerySysState = NULL;
+		}
+	}
+	return 0;
+}
+
+int os2_ftruncate(int fd, off_t size)
+{
+	// We call there __libc_Back_ioFileSizeSet directly instead of 
+        // ftruncate to force it not to zero expanding files to optimize
+        // samba performance when copying files
+	int rc = __libc_Back_ioFileSizeSet(fd, size, 0);
+	if (rc < 0)
+	{
+		errno = -rc;
+		return -1;
+	}
+	return 0;
+}
+
+#define   CMD_KI_RDCNT    (0x63)
+
+typedef struct _CPUUTIL {
+    ULONG ulTimeLow;            /* Low 32 bits of time stamp      */
+    ULONG ulTimeHigh;           /* High 32 bits of time stamp     */
+    ULONG ulIdleLow;            /* Low 32 bits of idle time       */
+    ULONG ulIdleHigh;           /* High 32 bits of idle time      */
+    ULONG ulBusyLow;            /* Low 32 bits of busy time       */
+    ULONG ulBusyHigh;           /* High 32 bits of busy time      */
+    ULONG ulIntrLow;            /* Low 32 bits of interrupt time  */
+    ULONG ulIntrHigh;           /* High 32 bits of interrupt time */
+} CPUUTIL;
+
+// very simple random data gatherer derived from openssl
+void os2_randget(char * buffer, int length)
+{
+	QWORD qwTime;
+	ULONG SysVars[QSV_FOREGROUND_PROCESS];
+	int done = 0;
+
+	if (!buffer || length <= 0)
+	{
+		return;
+	}
+
+	DosTmrQueryTime(&qwTime);
+	memcpy(buffer, &qwTime, sizeof(qwTime) > length ? length : sizeof(qwTime));
+	done += sizeof(qwTime);
+	if (done >= length)
+	{
+		return;
+	}
+
+	if (xDosPerfSysCall) 
+	{
+		CPUUTIL util;
+		if (xDosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) 
+		{
+			memcpy(buffer + done, &util, sizeof(util) > length - done ? length - done : sizeof(util));
+			done += sizeof(util);
+			if (done >= length)
+			{
+				return;
+			}
+		}
+	}
+
+#if 0
+	if (xDosQuerySysState) 
+	{
+		char *tmp = (char *)malloc(256 * 1024);
+		if (tmp)
+		{
+			if (xDosQuerySysState(0x1F, 0, 0, 0, tmp, 256 * 1024) == 0)
+			{
+				memcpy(buffer + done, tmp, 256 * 1024 > length - done ? length - done : 256 * 1024);
+				done += 256 * 1024;
+			}
+			free(tmp);
+		}
+	}
+	if (done >= length)
+	{
+		return;
+	}
+#endif
+
+	DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
+	memcpy(buffer + done, SysVars, sizeof(SysVars) > length - done ? length - done : sizeof(SysVars));
+}
+
+#include <InnoTekLIBC/tcpip.h>
+#undef close
+int debug_close(char * file, char * function, int line, int h )
+{
+	int os2socket = -1;
+	PLIBCSOCKETFH   pFHSocket = __libc_TcpipFH(h);	
+	if (pFHSocket) os2socket = pFHSocket->iSocket;
+	DEBUG(0,("close(%d (%d)) on %s:%s(%d)\n", h, os2socket, file, function, line));
+	return close(h);
+}
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/os2api.h	(revision 5)
@@ -0,0 +1,8 @@
+#ifndef __OS2__API__H_
+#define __OS2__API__H_
+
+int os2_init(void);
+int os2_ftruncate(int fd, off_t size);
+void os2_randget(char * buffer, int length);
+
+#endif /* __OS2__API__H_ */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/os2ea.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/os2ea.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/os2ea.c	(revision 5)
@@ -0,0 +1,474 @@
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSERRORS
+//_SMB_H
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+#ifndef TESTING
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#include "local.h"
+#include "xfile.h"
+#include "pstring.h"
+#include "debug.h"
+#else
+#define DEBUG(a,b) (0)
+#endif
+
+#include <string.h>
+
+#ifndef ENOATTR
+#define ENOATTR 22
+#endif
+
+static void maperrno(int rc)
+{
+	switch (rc)
+	{
+		case ERROR_PATH_NOT_FOUND    : 
+		case ERROR_FILE_NOT_FOUND    : errno = ENOENT; break;
+		case ERROR_INVALID_HANDLE    : errno = EBADF; break;
+		case ERROR_ACCESS_DENIED     : errno = EACCES; break;
+		case ERROR_BUFFER_OVERFLOW   :
+		case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
+		case ERROR_INVALID_EA_NAME   : errno = ENOATTR; break;
+		case ERROR_INVALID_LEVEL     :
+		case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
+		case ERROR_SHARING_VIOLATION : errno = EACCES; break;
+		default : errno = EINVAL;
+	}
+}
+
+static ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	EAOP2       eaop2 = {0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+	
+	if ((!path && !file) || !name)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;	
+	do
+	{
+		if (path)
+		{
+			char npath[CCHMAXPATH + 1] = {0};
+			strncpy(npath, path, CCHMAXPATH);
+			for (p = npath; *p; p++)
+			{
+				if (*p == '/') *p = '\\';
+			}
+			rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+		}
+		else
+		{
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+		}
+		if (rc)
+		{
+			maperrno(rc);
+			rc = -1;
+			break;
+		}
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
+		{
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value)
+		{
+			if (size < rc)
+			{
+				errno = ERANGE;
+				rc = -1;
+			}
+			else
+			{
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+	{
+		free(pgea2list);
+	}
+	if (pgea2list)
+	{
+		free(pfea2list);
+	}
+	DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
+	return rc;
+}
+
+ssize_t getxattr (const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t lgetxattr (const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t fgetxattr (int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+static ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat = {0};
+	char npath[CCHMAXPATH + 1] = {0};
+	if (!path && !file)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	if (path)
+	{
+		char * p;
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+		rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
+	}
+	else
+	{
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+	}
+	if (rc)
+	{
+		DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
+		maperrno(rc);
+		return -1;		
+	}
+	if (stat.cbList <= 4)
+	{
+		// NO ea
+		return 0;
+	}
+	buf = (char *)malloc(stat.cbList * 2);
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc)
+	{
+		DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
+		maperrno(rc);
+		free(buf);
+		return -1;
+	}
+	if (ulCount > 0)
+	for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
+	{
+		if (pfea->cbName > 0)
+		{
+			gotsize += pfea->cbName + 1;
+			if (p && size >= gotsize)
+			{
+				pfea->szName[pfea->cbName] = 0;
+				strcpy(p, pfea->szName);
+				p += strlen(p) + 1;
+			}
+		}
+		if (!pfea->oNextEntryOffset)
+		{
+			break;
+		}
+	}
+	free(buf);
+	DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
+	if (gotsize > size)
+	{
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	return gotsize;
+}
+
+ssize_t listxattr (const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t llistxattr (const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t flistxattr (int file, char *list, size_t size)
+{
+	return unilistxattr(0, file, list, size);
+}
+
+static int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path)
+	{
+		char npath[CCHMAXPATH + 1] = {0};
+		char * p;
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+		rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+	}
+	else
+	{
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+	}
+	if (rc)
+	{
+		maperrno(rc);
+		return -1;
+	}
+	return 0;
+}
+
+int removexattr (const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+int lremovexattr (const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+int fremovexattr (int file, const char *name)
+{
+	return uniremovexattr (0, file, name);
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+static int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0};
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+	
+	if ((!path && !file) || !name || (!value && size))
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE))
+	{
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0)
+		{
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0)
+		{
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(GEALIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value)
+	{
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;	
+
+	if (path)
+	{
+		char npath[CCHMAXPATH + 1] = {0};
+		char * p;
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+		rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+	}
+	else
+	{
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+	}
+	free(pfea2list);
+	if (rc)
+	{
+		maperrno(rc);
+		return -1;
+	}
+	return 0;
+}
+
+int setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
+{
+	return unisetxattr (path, 0, name, value, size, flags);
+}
+
+int lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
+{
+	return unisetxattr (path, 0, name, value, size, flags);
+}
+
+int fsetxattr (int file, const char *name, const void *value, size_t size, int flags)
+{
+	return unisetxattr (0, file, name, value, size, flags);
+}
+
+#ifdef TESTING
+#include <fcntl.h>
+#include <sys/stat.h>
+
+ int main(int argc, char ** argv)
+{
+	int rc;
+	if (argc < 2)
+	{
+		char * p = strrchr(*argv, '\\');
+		p = p ? p + 1 : *argv;
+		printf("Usage: %s <file1> [<file2> ...]\n", p);
+		return 1;
+	}
+	for (argc--, argv++; argc > 0; argc--, argv++)
+	{
+		char * ealist, * p;
+		ssize_t ealistsize;
+		printf("Processing file <%s>\n", *argv);
+		ealistsize = listxattr(*argv, 0, 0);
+		printf("EA list size %ld\n", ealistsize);
+/*
+		if (ealistsize)
+		{
+			continue;
+		}
+*/
+		ealist = malloc(ealistsize);
+		ealistsize = listxattr(*argv, ealist, ealistsize);
+		printf("EA list size2 %ld\n", ealistsize);
+		if (ealistsize > 0)
+		{
+			int file = open(*argv, O_RDWR | O_BINARY, S_IREAD | S_IWRITE);
+			if (file < 0)
+			{
+				printf("Cant open file <%s> : %d\n", *argv, errno);
+				continue;
+			}
+			for (p = ealist; (p - ealist) < ealistsize && *p; p += strlen(p) + 1)
+			{
+				ssize_t easize;
+				unsigned char * eavalue;
+				printf("EA name <%s>\n", p);
+				easize = fgetxattr(file, p, 0, 0);
+				printf("EA size %ld\n", easize);
+				eavalue = malloc(easize);
+				easize = fgetxattr(file, p, eavalue, easize);
+				printf("EA size2 %ld\n", easize);
+/*
+				if (easize > 0)
+				{
+					unsigned char * q;
+					printf("Eavalue :");
+					for (q = eavalue; q - eavalue < easize; q++)
+					{
+						printf(" %02x", *q);
+					}
+					printf("\n");
+				}
+*/
+				free(eavalue);
+			}
+			rc = fremovexattr(file, ealist);
+			printf("remove <%s> rc %d\n", ealist, rc);
+	
+			rc = fsetxattr(file, "XYZ3", "QWERTY", 6, 0);
+			printf("set rc %d\n", rc);
+/*
+			rc = fsetxattr(file, "XYZ3", "QWERTY", 6, XATTR_REPLACE);
+			printf("set rc %d\n", rc);
+*/
+			free(ealist);
+			close(file);
+		}
+	}
+	return 0;
+}
+#endif
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.c	(revision 5)
@@ -0,0 +1,22 @@
+// OS/2 stuff to support multithreading for some 'global' variables
+
+#include "includes.h"
+
+#ifdef USE_OS2MT_STUFF
+
+static int cligettid()
+{
+	int tid = _gettid();
+	if (tid < 0 || tid > SMBCD_MAX_THREADS)
+	{
+		tid = 0;
+	}
+	return tid;
+}
+
+MTFUNC(int, smb_read_error)
+MTFUNC(struct in_addr, lastip)
+MTFUNC(int, lastport)
+MTFUNC(TALLOC_CTX*, list_head)
+
+#endif
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/os2mt.h	(revision 5)
@@ -0,0 +1,30 @@
+#ifndef _OS2MT_H_
+#define _OS2MT_H_
+
+#ifdef USE_OS2MT_STUFF
+
+#define MTFUNC(type,name)\
+type name##_array[SMBCD_MAX_THREADS] = {0}; \
+type *_##name() \
+{\
+	return name##_array + cligettid(); \
+}
+
+extern int *_smb_read_error();
+#define smb_read_error (*_smb_read_error())
+
+extern struct in_addr *_lastip();
+#define lastip (*_lastip())
+
+extern int *_lastport();
+#define lastport (*_lastport())
+
+extern int *_lastport();
+#define lastport (*_lastport())
+
+extern TALLOC_CTX **_list_head();
+#define list_head (*_list_head())
+
+#endif /* USE_OS2MT_STUFF */
+
+#endif /* _OS2MT_H_ */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.dlg
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.dlg	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.dlg	(revision 5)
@@ -0,0 +1,67 @@
+#ifndef OS2_INCLUDED
+   #include <os2.h>
+#endif
+DLGINCLUDE 1 "rc.h"
+
+DLGTEMPLATE DLG_ID LOADONCALL MOVEABLE DISCARDABLE
+BEGIN
+    DIALOG  "", DLG_ID, 5, 5, 200, 140, WS_VISIBLE, FCF_SYSMENU | 
+            FCF_TITLEBAR
+    BEGIN
+        CTEXT           "SMB resource properties:", LBL_PROP, 5, 129, 190, 10, 
+                        DT_VCENTER
+
+        RTEXT           "Workgroup:", LBL_WORKGRP, 5, 117, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_WORKGRP, 67, 118, 100, 8, ES_MARGIN
+
+        RTEXT           "Server:", LBL_SERVER, 5, 105, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_SERVER, 67, 106, 100, 8, ES_MARGIN
+
+        RTEXT           "Share:", LBL_SHARE, 5, 93, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_SHARE, 67, 94, 100, 8, ES_MARGIN
+
+        RTEXT           "User:", LBL_USER, 5, 81, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_USER, 67, 82, 100, 8, ES_MARGIN
+
+        RTEXT           "Password:", LBL_PASS, 5, 69, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_PASS, 67, 70, 100, 8, ES_MARGIN
+
+        RTEXT           "Master", LBL_MASTER, 5, 57, 30, 10, 
+                        DT_BOTTOM
+        CONTROL         "", CMB_MASTER, 37, 35, 50, 33, WC_COMBOBOX, 
+                        CBS_DROPDOWNLIST | WS_GROUP | WS_TABSTOP | 
+                        WS_VISIBLE
+        ENTRYFIELD      "", ENT_MASTER, 89, 58, 78, 8, ES_MARGIN
+        RTEXT           "Memory buffer:", LBL_MEMLEN, 5, 45, 60, 10, 
+                        DT_BOTTOM
+        CONTROL         "", CMB_MEMLEN, 67, 1, 50, 54, WC_COMBOBOX, 
+                        CBS_DROPDOWNLIST | WS_GROUP | WS_TABSTOP | 
+                        WS_VISIBLE
+
+        RTEXT           "Logfile:", LBL_LOGFILE, 5, 33, 60, 10, 
+                        DT_BOTTOM
+        ENTRYFIELD      "", ENT_LOGFILE, 67, 33, 100, 8, ES_MARGIN
+
+        RTEXT           "Loglevel:", LBL_LOGLEVEL, 5, 21, 60, 10, 
+                        DT_BOTTOM
+        CONTROL         "", CMB_LOGLEVEL, 67, 18, 20, 35, WC_SPINBUTTON, 
+                        SPBS_NUMERICONLY | SPBS_JUSTRIGHT | SPBS_MASTER | WS_GROUP | WS_TABSTOP | 
+                        WS_VISIBLE
+
+        LTEXT           "EA Support", LBL_EASUPPORT, 121, 20, 50, 10, 
+                        DT_BOTTOM
+        CONTROL         "", CHK_EASUPPORT, 110, 20, 10, 10, WC_BUTTON, 
+                        BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP | 
+                        WS_VISIBLE
+
+        PUSHBUTTON      "Cancel", DID_CANCEL, 2, 2, 40, 14
+        PUSHBUTTON      "<<Previous", BTN_PREV, 49, 2, 59, 14
+        DEFPUSHBUTTON   "Done", DID_OK, 113, 2, 40, 14
+        PUSHBUTTON      "Help", BTN_HELP, 158, 2, 40, 14, BS_HELP
+    END
+END
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.h	(revision 5)
@@ -0,0 +1,25 @@
+#define BTN_HELP                    10
+#define BTN_PREV                    11
+#define DLG_ID                      1000
+#define LBL_WORKGRP                 1001
+#define ENT_WORKGRP                 1002
+#define LBL_SERVER                  1003
+#define ENT_SERVER                  1004
+#define LBL_SHARE                   1005
+#define ENT_SHARE                   1006
+#define LBL_USER                    1007
+#define ENT_USER                    1008
+#define LBL_PASS                    1009
+#define ENT_PASS                    1010
+#define LBL_MASTER                  1011
+#define ENT_MASTER                  1012
+#define CMB_MASTER                  1013
+#define LBL_MEMLEN                  1014
+#define CMB_MEMLEN                  1015
+#define LBL_PROP                    1016
+#define LBL_LOGFILE                 1017
+#define ENT_LOGFILE                 1018
+#define LBL_LOGLEVEL                1019
+#define CMB_LOGLEVEL                1020
+#define LBL_EASUPPORT               1021
+#define CHK_EASUPPORT               1022
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.ipf
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.ipf	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.ipf	(revision 5)
@@ -0,0 +1,57 @@
+#include <hmacros.h>
+#include "rc.h"
+
+:userdoc.
+
+.nameit symbol=nd text='NetDrive for OS/2'
+.nameit symbol=ndcp text='NetDrive for OS/2 Control Panel'
+.nameit symbol=mp text='mount point'
+.nameit symbol=ressmb text='SAMBA Resource Properties'
+
+:title.NetDrive for OS/2 Control Panel Help
+
+:docprof toc=123456.
+.******************************************************
+
+.******************************************************
+HEADING(1, DLG_ID)&ressmb.
+PINDEX(ressmb)&ressmb.
+:p.
+The parameters of a SMB FS resource are&colon.
+:parml.
+:pt.Workgroup
+:pd.Name of workgroup
+
+:pt.Server
+:pd.Name or IP address of server to connect to.
+
+:pt.Share
+:pd.Name of share to connect to.
+
+:pt.User
+:pd.Name of user to log in.
+
+:pt.Password
+:pd.Password of user.
+
+:pt.Master
+:pd.Name of master workgroup or server.
+
+:pt.Mastertype
+:pd.0 if 'master' is the name of master server, 1 if 'master' is the name of master workgroup.
+
+:pt.Memlen
+:pd.The size of shared memory buffer allocated for every NDFS connection in size of 64k blocks.
+
+:pt.Logfile
+:pd.File to log records from smbcd.exe. Used only if smbcd.exe is run by ndpsmb.dll plugin, not manually.
+
+:pt.Loglevel
+:pd.Level of logging (0-9) for smbcd.exe. Used only if smbcd.exe is run by ndpsmb.dll plugin, not manually.
+
+:pt.EA Support
+:pd.Switches on/off EA support.
+
+:eparml.
+.******************************************************
+:euserdoc.
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.rc
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.rc	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/rc/rc.rc	(revision 5)
@@ -0,0 +1,147 @@
+#include <ndpl_rc.h>
+
+#include "rc.h"
+
+RCINCLUDE "rc.dlg"
+
+RCDATA NDRC_PLUGIN_NAME
+{
+    "SMBFS"
+}
+
+RCDATA NDRC_PLUGIN_DESC
+{
+    "Access to SAMBA resources."
+}
+
+RCDATA NDRC_PLUGIN_HELP
+{
+    "ndpsmb.hlp"
+}
+
+/* if dlg is the same for two types then one dlg id may be specified
+   for both descriptions (this is untested however :) */
+RCDATA NDRC_TYPE_FIRST
+{
+    DLG_ID, "SMBFS."
+}
+
+
+RCDATA NDRC_TYPE_HELP_FIRST
+{
+   "Help for command line utility:\r\n"
+   "\r\n"
+   "nd mount smbfs s:\\mountpoint ;workgroup=...;server=...;share=...;user=...;password=...;master=...;mastertype=...;memlen=...;logfile=...;loglevel=...;easupport=...\r\n"
+   "\r\n"
+   "    workgroup - name of workgroup\r\n"
+   "    server - name or ip address of server\r\n"
+   "    share - name of share\r\n"
+   "    user - name of user\r\n"
+   "    password - user password\r\n"
+   "    master - name of master server or master workgroup\r\n"
+   "    mastertype - 0 if 'master' is the name of master server, 1 if 'master' is the name of master workgroup\r\n"
+   "    memlen - the size of shared memory buffer allocated for every NDFS connection in size of 64k blocks\r\n"
+   "    logfile - file to log records from smbcd.exe. Used only if smbcd.exe is run by ndpsmb.dll plugin, not manually\r\n"
+   "    loglevel - level of logging (0-9) for smbcd.exe. Used only if smbcd.exe is run by ndpsmb.dll plugin, not manually\r\n"
+   "    easupport - 0 to not support EA, 1 to support\r\n"
+   "\r\n"
+}
+
+HELPTABLE DLG_ID
+{
+    HELPITEM DLG_ID, DLG_ID, DLG_ID
+}
+
+HELPSUBTABLE DLG_ID
+SUBITEMSIZE 2
+{
+}
+
+/* 
+ * ID, TYPE, REQUIRED, RANGE_LOW, RANGE_HIGH, "NAME", "FORMATSTRING", "DEFAULT" or DEFAULT
+ */
+
+RCDATA DLG_ID
+{
+    ENT_WORKGRP, PARMTYPE_STRING, 1L, 256L, "workgroup", "%s", ""
+}
+
+RCDATA (DLG_ID + 1)
+{
+    ENT_SERVER, PARMTYPE_STRING, 1L, 256L, "server", "%s", ""
+}
+
+RCDATA (DLG_ID + 2)
+{
+    ENT_SHARE, PARMTYPE_STRING, 1L, 256L, "share", "%s", ""
+}
+
+RCDATA (DLG_ID + 3)
+{
+    ENT_USER, PARMTYPE_STRING, 1L, 256L, "user", "%s", "guest"
+}
+
+RCDATA (DLG_ID + 4)
+{
+    ENT_PASS, PARMTYPE_STRING, 1L, 256L, "password", "%s", ""
+}
+
+RCDATA (DLG_ID + 5)
+{
+    ENT_MASTER, PARMTYPE_STRING, 1L, 256L, "master", "%s", "WORKGROUP"
+}
+
+RCDATA (DLG_ID + 6)
+{
+    CMB_MASTER, PARMTYPE_INT, 0L, 1L, "mastertype", "%d", 1L, 
+    "server", 
+    "workgroup"
+}
+
+RCDATA (DLG_ID + 7)
+{
+    CMB_MEMLEN, PARMTYPE_INT, 1L, 10L, "memlen", "%d", 2L, 
+    "64k", 
+    "128k", 
+    "192k", 
+    "256k", 
+    "320k", 
+    "384k", 
+    "448k", 
+    "512k", 
+    "576k", 
+    "640k"
+}
+
+RCDATA (DLG_ID + 8)
+{
+    ENT_LOGFILE, PARMTYPE_STRING, 1L, 256L, "logfile", "%s", ""
+}
+
+RCDATA (DLG_ID + 9)
+{
+    CMB_LOGLEVEL, PARMTYPE_INT, 0L, 9L, "loglevel", "%d", 0L, 
+    "0", 
+    "1",
+    "2",
+    "3",
+    "4",
+    "5",
+    "6",
+    "7",
+    "8",
+    "9"
+}
+
+RCDATA (DLG_ID + 10)
+{
+    CHK_EASUPPORT, PARMTYPE_INT, 0L, 1L, "easupport", "%d", 1L, 
+    "0", 
+    "1"
+}
+    
+RCDATA (DLG_ID + 11)
+{
+    0
+}
+
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/readme.txt
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/readme.txt	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/readme.txt	(revision 5)
@@ -0,0 +1,198 @@
+                           OS/2 SAMBA client
+                           _________________
+
+CONTENTS
+________
+
+ 1. Introduction
+ 2. License
+ 3. Installation
+ 4. SMBCD.EXE usage
+ 5. NDPSMB.DLL usage
+ 6. Changelog
+
+
+1. Introduction
+_______________
+
+SAMBA is a SMB/CIFS protocols file and print sharing server/client set originaly
+made for UNIX world to cooperate with corresponding Windows and OS/2 servers or
+clients. OS/2 has native implementation of SMB/CIFS server/client set - IBM LAN
+Manager and IBM Peer. These products haven't been updated for a long time and
+have some compatibility problems with modern Windows SMB/CIFS implementations.
+
+This package is the OS/2 port of SAMBA 3.0.9 client made as the plugin to
+NetDrive - a well known virtual file system for OS/2. OS/2 SAMBA client provides
+seamles access to SMB/CIFS file shares over your network using TCP/IP as the
+underlying transport protocol.
+
+The OS/2 SAMBA client consists of two modules:
+   ndpsmb.dll - the NetDrive plugin itself.
+   smbcd.exe  - the SAMBA client daemon, which actually processes the requests
+                from ndpsmb.dll.
+
+
+2. License
+__________
+
+SAMBA is freely available under the GNU General Public License. You can get
+the full sourcecode from our CVS repository, please refer to the SAMBA for OS/2
+and eCS Homepage for details about downloading the source.
+
+The NetDrive plugin is also available with full sourcecode.
+However, netlabs.org hired nickk to port SAMBA to OS/2 and to create the
+NetDrive plugin. Future work on this plugin highly depends on the support of
+the OS/2 and eCS community. We also think about providing a SAMBA server
+implementation for OS/2 and eCS but that will cost money too.
+
+So if you are using our plugin we kindly ask you to support netlabs.org.
+Please refer to the SAMBA for OS/2 and eCS Homepage to learn how you can do
+that!
+
+NOTE: The current beta release needs NetDrive for OS/2. NetDrive is shareware
+but we are in contact with the developer of it, probably there will be a free
+stripped down SAMBA-only version of NetDrive when we release the final version.
+(Don't take that for granted yet, we will announce that in the future)
+
+Links:
+
+SAMBA for OS/2 and eCS Homepage: http://samba.netlabs.org/
+NetDrive Homepage: http://www.blueprintsoftwareworks.com/netdrive/
+SAMBA Homepage: http://www.samba.org/
+
+
+3. Installation
+_______________
+
+You must have NetDrive 2.2.1 or newer installed prior to installation of this
+package. If you want to use 64bit file API, you should install 2.3 or newer
+version of NetDrive. The installation is semi-automatic and consists of two 
+steps:
+
+  - libc installation :
+      Put libc06*.dll included into this package (the innotek gcc runtime dll) 
+      somewhere in your LIBPATH, if it is not here already.
+
+  - ndpsmb.dll and smbcd.exe installation :
+      Run instpl.cmd from this package. The installer will place smbcd.exe in 
+      the Netdrive home directory. When you will connect to CIFS share using the
+      ndpsmb plugin, it will start the smbcd.exe  automatically from this 
+      directory. However, you can start it manually, if you want.
+
+4. SMBCD.EXE Usage
+__________________
+
+SMBCD.EXE has the following parameters:
+  -d <debuglevel> (or --debug <debuglevel>) - debug level of output from 0 to 9.
+The more debug level provides more debugging output from SMBCD.EXE which may 
+be used to solve the problems.
+  -l <logfile> (or --logfile <logfile>) - the filename to write the debug info
+from smbcd.exe. Default is to print all debug info to STDOUT stream.
+  -q (or --quite) - tells smbcd.exe to be absolutely quiet.
+
+5. NDPSMB.DLL Usage
+___________________
+
+NetDrive SAMBA plugin is used according to general NetDrive usage rules. Read
+the NetDrive documentation for more information. The SMB/CIFS resources could
+be mounted either using command line nd.exe utility or WPS ndpm.exe utility of
+NetDrive.
+
+The NetDrive SAMBA plugin parameters are:
+
+   workgroup   - the name of workgroup to connect to.
+   server      - the name of server to connect to.
+   share       - the name of server resource (share) to connect to.
+   user        - the name of user to login under.
+   password    - the password of selected user.
+   master      - the name of 'master' server or workgroup, used to get the list
+                 of workgroups when the concrete workgroup and server not
+                 specified.
+   masterttype - 0 if 'master' is the name of master server, 1 if 'master' is
+                 the name of master workgroup.
+   memlen      - the size of shared memory buffer allocated for every connection
+                 to SBM/CIFS resources in size of 64k blocks. The higher values
+                 could provide better access speed, but consume more memory.
+   logfile     - file to log records from smbcd.exe. Used only in smbcd.exe 
+                 is run by ndpsmb.dll plugin, not manually
+   loglevel    - level of logging (0-9) for smbcd.exe. Used only in smbcd.exe 
+                 is run by ndpsmb.dll plugin, not manually
+   easupport   - 1 to support OS/2 Extended Attributes, 0 to not support it
+
+To mount the a exact server's share one need to specify both 'server' and
+'share' parametres, the other parametres are optional. The root path of
+server's share will be mounted to the mounting path.
+
+If one want to access all servers shares, the only the 'server', not the 'share'
+parameter, should be specified,the other parametres are optional. The list of
+server's shares will be mounted to the mounting path.
+
+If one want to access all servers within the workgroup, the only the 'workgroup',
+not the 'server' parameter, should be specified, the other parametres are
+optional. The list of servers within the specified workgroup will be mounted to
+the mounting path.
+
+If one want to access all available workgroups within one master browser
+in network, the only the 'master', not the 'workgroup' or 'server' parameter,
+should be specified, the other parametres are optional. The list of workgroups
+will be mounted to the mounting path. The 'master' workgroup can be any known
+workgroup in the net. The 'master' server should be the master browser for
+workgroup[s].
+
+By default the 'guest' user with blank password is used to access selected
+resources. If you get access denied (5) errors, try to specify another user and
+password combination.
+
+6. Changelog
+____________
+
+ beta3:
+   - changelog created
+   - fixed a bug with several network interfaces on one system
+   - fixed a bug with broken cmd.exe builtin commands
+   - fixed a bug with wrong dates of new and modified files
+   - fixed a bunch of other bugs which are too small to remember ;)
+   - smbcd.exe compiled against old tcp/ip stack interface
+
+ beta4:
+   - fixed errors on write to eCs shares
+   - more fixes for wrong dates of files
+
+ beta5:
+   - added file locking
+   - added 64bit file IO (when working with NDFS 2.3+)
+   - moved to 3.0.9 samba code
+
+ beta6:
+   - fixed set attribute bug introduced in beta 5
+   - implemented setnewfilesize function. It may work not on all CIFS servers.
+   - added automatic smbcd.exe starting if not started when connecting to CIFS share
+   - added 'logfile' and 'loglevel' options to ndpsmb
+
+ beta7:
+   - moved to libc06b4.dll libc.
+
+ beta8:
+   - moved back to libc custom build. 
+   - added EA support
+   - a bunch of bugs fixed
+
+ beta9:
+   - added EA support for DosOpen which was forgotten in beta8
+
+ beta10:
+   - caching of EA size after file find request
+   - moved to libc06b5.dll libc
+
+ beta11:
+   - moved to libc06r1.dll libc
+
+ beta12:
+   - NdpRsrcQueryFSAllocate rewritten
+   - moved to libc06.dll from GA2 release
+
+ beta13, the lucky one:
+   - moved to libc061.dll from CSD1 release
+
+ beta14:
+   - moved to libc custom build
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.c	(revision 5)
@@ -0,0 +1,883 @@
+#define INCL_DOSERRORS
+#define INCL_DOS
+#include <os2emx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <process.h>
+#include <sys/time.h>
+#include "smbwrp.h"
+#include "smbcd.h"
+
+int debuglevel = 0;
+HMTX logmutex = 0;
+char *logfile = NULL;
+
+char *timestring(int hires);
+
+int debug_parse_levels(const char *params_str)
+{
+	return 1;
+}
+
+void dbgflush( void )
+{
+//	if (!logfile) fflush(stdout);
+}
+
+int debuglvl(int level)
+{
+	return (level <= debuglevel) ? 1 : 0;
+}
+
+int debugheader(int level, char * file, char * func, int line)
+{
+	int rc;
+	if (level > debuglevel)
+	{
+		return 0;
+	}
+	rc = DosRequestMutexSem(logmutex, -1L);
+	if (rc)
+	{
+		return 0;
+	}
+	rc = 1;
+	do
+	{
+		FILE * f;
+		struct timeval tv;
+		time_t t;
+		char buf[80] = {0};
+		if (logfile)
+		{
+			f = fopen(logfile, "a");
+			if (!f)
+			{
+				rc = 0;
+				break;
+			}
+		}
+		else
+		{
+			f = stdout;
+		}
+		gettimeofday(&tv, NULL);
+		t = time(NULL);
+//		strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
+		strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
+		fprintf(f, "%s.%d: %d %d: %s:%s(%d) :", buf, tv.tv_usec / 10000, level, _gettid(), file, func, line);
+		if (logfile)
+		{
+			fclose(f);
+		}
+	}
+	while (0);
+	DosReleaseMutexSem(logmutex);
+	return rc;
+}
+
+int debugmessage(char * fmt, ...)
+{
+	int rc;
+	rc = DosRequestMutexSem(logmutex, -1L);
+	if (rc)
+	{
+		return 0;
+	}
+	do
+	{
+		FILE * f;
+		va_list args;
+		if (logfile)
+		{
+			f = fopen(logfile, "a");
+			if (!f)
+			{
+				break;
+			}
+		}
+		else
+		{
+			f = stdout;
+		}
+		va_start(args, fmt);
+		vfprintf(f, fmt, args);
+		va_end(args);
+		if (logfile)
+		{
+			fclose(f);
+		}
+	}
+	while (0);
+	DosReleaseMutexSem(logmutex);
+	return 0;
+}
+
+void debuglocal(int level, char * fmt, ...)
+{
+	int rc;
+	if (level > debuglevel)
+	{
+		return;
+	}
+	rc = DosRequestMutexSem(logmutex, -1L);
+	if (rc)
+	{
+		return;
+	}
+	do
+	{
+		FILE * f;
+		struct timeval tv;
+		char buf[80] = {0};
+		va_list args;
+		if (logfile)
+		{
+			f = fopen(logfile, "a");
+			if (!f)
+			{
+				break;
+			}
+		}
+		else
+		{
+			f = stdout;
+		}
+		gettimeofday(&tv, NULL);
+		strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
+		fprintf(f, "%s.%d: %d %d: ", buf, tv.tv_usec / 10000, level, _gettid());
+		va_start(args, fmt);
+		vfprintf(f, fmt, args);
+		va_end(args);
+		if (logfile)
+		{
+			fclose(f);
+		}
+	}
+	while (0);
+	DosReleaseMutexSem(logmutex);
+}
+
+// map errno errors to API errors
+int maperror(int rc)
+{
+	switch (rc)
+	{
+		case 0 : return NO_ERROR ; /* NO_ERROR */
+		case 1 : return ERROR_ACCESS_DENIED ; /* EPERM -  Operation not permitted               */
+		case 2 : return ERROR_FILE_NOT_FOUND ; /* ENOENT -  No such file or directory             */
+		case 3 : return ERROR_PID_MISMATCH ; /* ESRCH -  No such process                       */
+		case 4 : return ERROR_INTERRUPT ; /* EINTR -  Interrupted system call               */
+		case 5 : return ERROR_READ_FAULT ; /* EIO -  I/O error                             */
+		case 6 : return ERROR_BAD_UNIT ; /* ENXIO -  No such device or address             */
+		case 7 : return ERROR_INVALID_DATA ; /* E2BIG -  Arguments or environment too big      */
+		case 8 : return ERROR_BAD_EXE_FORMAT ; /* ENOEXEC -  Invalid executable file format        */
+		case 9 : return ERROR_INVALID_HANDLE ; /* EBADF -  Bad file number                       */
+		case 10 : return ERROR_NO_CHILD_PROCESS ; /* ECHILD -  No child processes                    */
+		case 11 : return ERROR_BUSY ; /* EAGAIN -  Resource temporarily unavailable      */
+		case 12 : return ERROR_NOT_ENOUGH_MEMORY ; /* ENOMEM -  Not enough memory                     */
+		case 13 : return ERROR_ACCESS_DENIED ; /* EACCES -  Permission denied                     */
+		case 14 : return ERROR_INVALID_ADDRESS ; /* EFAULT -  Bad address                           */
+		case 15 : return ERROR_NOT_LOCKED ; /* ENOLCK -  No locks available                    */
+		case 16 : return ERROR_BUSY ; /* EBUSY -  Resource busy                         */
+		case 17 : return ERROR_FILE_EXISTS ; /* EEXIST -  File exists                           */
+		case 18 : return ERROR_NOT_SAME_DEVICE ; /* EXDEV -  Cross-device link                     */
+		case 19 : return ERROR_REM_NOT_LIST ; /* ENODEV -  No such device                        */
+		case 20 : return ERROR_PATH_NOT_FOUND ; /* ENOTDIR -  Not a directory                       */
+		case 21 : return ERROR_DIRECTORY ; /* EISDIR -  Is a directory                        */
+		case 22 : return ERROR_INVALID_PARAMETER ; /* EINVAL -  Invalid argument                      */
+		case 23 : return ERROR_TOO_MANY_OPEN_FILES ; /* ENFILE -  Too many open files in system         */
+		case 24 : return ERROR_TOO_MANY_OPENS ; /* EMFILE -  Too many open files                   */
+		case 25 : return ERROR_MOD_NOT_FOUND ; /* ENOTTY -  Inappropriate ioctl                   */
+		case 26 : return ERROR_LOCK_VIOLATION ; /* EDEADLK -  Resource deadlock avoided             */
+		case 27 : return ERROR_TRANSFER_TOO_LONG ; /* EFBIG -  File too large                        */
+		case 28 : return ERROR_DISK_FULL ; /* ENOSPC -  Disk full                             */
+		case 29 : return ERROR_SEEK ; /* ESPIPE -  Invalid seek                          */
+		case 30 : return ERROR_WRITE_PROTECT ; /* EROFS -  Read-only file system                 */
+		case 31 : return ERROR_TOO_MANY_OPEN_FILES ; /* EMLINK -  Too many links                        */
+		case 32 : return ERROR_BROKEN_PIPE ; /* EPIPE -  Broken pipe                           */
+		case 33 : return ERROR_INVALID_LEVEL ; /* EDOM -  Domain error                          */
+		case 34 : return ERROR_FILENAME_EXCED_RANGE ; /* ERANGE -  Result too large                      */
+		case 35 : return ERROR_DIR_NOT_EMPTY ; /* ENOTEMPTY -  Directory not empty                   */
+		case 36 : return ERROR_BUSY_DRIVE ; /* EINPROGRESS -  Operation now in progress             */
+		case 37 : return ERROR_INVALID_FUNCTION ; /* ENOSYS -  Function not implemented              */
+		case 38 : return ERROR_FILENAME_EXCED_RANGE ; /* ENAMETOOLONG -  File name too long                    */
+		case 39 : return ERROR_KBD_FOCUS_REQUIRED ; /* EDESTADDRREQ -  Destination address required          */
+		case 40 : return ERROR_TRANSFER_TOO_LONG ; /* EMSGSIZE -  Message too long                      */
+		case 48 : return ERROR_NETWORK_BUSY ; /* EADDRINUSE -  Address already in use                */
+		case 49 : return ERROR_INFO_NOT_AVAIL ; /* EADDRNOTAVAIL -  Can't assigned requested address      */
+		case 50 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETDOWN -  Network is down                       */
+		case 51 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETUNREACH -  Network is unreachable                */
+		case 52 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETRESET -  Network dropped connection on reset   */
+		case 53 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNABORTED -  Software caused connection abort      */
+		case 54 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNRESET -  Connection reset by peer              */
+		case 55 : return ERROR_BUFFER_OVERFLOW ; /* ENOBUFS -  No buffer space available             */
+		case 56 : return ERROR_PIPE_BUSY ; /* EISCONN -  Socket is already connected           */
+		case 57 : return ERROR_PIPE_NOT_CONNECTED ; /* ENOTCONN -  Socket is not connected               */
+		case 58 : return ERROR_ALREADY_SHUTDOWN ; /* ESHUTDOWN -  Can't send after socket shutdown      */
+		case 60 : return ERROR_TIMEOUT ; /* ETIMEDOUT -  Connection timed out                  */
+		case 61 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNREFUSED -  Connection refused                    */
+		case 63 : return ERROR_INVALID_BLOCK ; /* ENOTSOCK -  Socket operation on non-socket        */
+		case 64 : return ERROR_BAD_FORMAT ; /* EHOSTDOWN -  Host is down                          */
+		case 65 : return ERROR_BAD_NETPATH ; /* EHOSTUNREACH -  No route to host                      */
+		case 66 : return ERROR_BUSY_DRIVE ; /* EALREADY -  Operation already in progress         */
+	}
+	return rc + 40000;
+}
+
+char * getlastslash(char * path)
+{
+	char * p;
+	if (!path)
+	{
+		return NULL;
+	}
+	for (p = path + strlen(path) - 1; p >= path; p--)
+	{
+		if (*p == '\\' || *p == '/')
+		{
+			return p;
+		}
+	}
+	return NULL;
+}
+
+void _System add_dir_entry(void * st)
+{
+	int rc;
+	filelist_state * state = (filelist_state *)st;
+	if (!state || !*(state->finfo.fname))
+	{
+		return;
+	}
+	if (!state->data)
+	{
+		debuglocal(0,"Malformed filelist_state!\n");
+		return;
+	}
+	if (state->bufferlen < state->datalen + sizeof(state->finfo))
+	{	
+		// send this portion of buffer to client
+		smb_request req = {0};
+		smb_response resp = {0};
+		unsigned long action;
+		resp.length = state->datalen;
+		resp.rc = ERROR_MORE_DATA;
+		rc = DosWrite(state->pipe, &resp, sizeof(resp), &action);
+		if (rc || action < sizeof(resp))
+		{
+			debuglocal(1,"Failed to write to pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
+		}
+		else
+		{
+			rc = DosRead(state->pipe, &req, sizeof(req), &action);
+			if (rc || action < sizeof(req))
+			{
+				debuglocal(0,"Failed to read from pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
+				return;
+			}
+		}
+		state->datalen = 0;
+	}
+	memcpy(state->data + state->datalen, &state->finfo, sizeof(state->finfo));
+	state->datalen += sizeof(state->finfo);
+}
+
+// rc = 0 - continue, rc = 1 - quit with response
+int processrequest(HPIPE pipe, cli_state * cli, unsigned long * reconnect, smbwrp_server * srv, smb_request *req, smb_response *res)
+{
+	int rc = 0;
+	int callrc = 0;
+	char * data;
+	if (!pipe || !cli || !reconnect || !srv || !req || !req->param || req->paramlen > req->length || !res)
+	{
+		debuglocal(0,"invalid structures\n");	
+		return ERROR_INVALID_PARAMETER;
+	}
+	data = req->param + req->paramlen;
+//	memset(res, 0, sizeof(*res));
+	debuglocal(1,"Client request %d paramlen %d len %d, reconnect %d. State %08x\n",  req->request, req->paramlen, req->length, *reconnect, cli);
+	if (*reconnect == 2)
+	{
+		debuglocal(1,"Reconnecting to last server requested\n");
+		res->rc = smbwrp_connect(srv, cli);
+		if (res->rc)
+		{
+			debuglocal(1,"Client reconnect resprc %d\n",  res->rc);
+			return NO_ERROR;
+		}
+		*reconnect = 1;
+	}
+	switch (req->request)
+	{
+		case SMBREQ_INIT :
+		{
+			res->value = sizeof(smbwrp_server) << 16 | getpid();
+		} break;
+		case SMBREQ_INITCOMPLETE :
+		{
+			callrc = DosGetSharedMem(req->param, PAG_READ | PAG_WRITE);
+			if (callrc)
+			{
+				debuglocal(0,"Cant get sharedmem of %x : %d\n", req->param, callrc);
+				res->rc = callrc;
+				rc = 1;
+				break;
+			}
+		} break;
+		case SMBREQ_CONNECT :
+		{
+			if (req->paramlen < sizeof(smbwrp_server))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			res->rc = smbwrp_connect((smbwrp_server *)req->param, cli);
+			if (!res->rc)
+			{
+				memcpy(srv, req->param, sizeof(smbwrp_server));
+				*reconnect = 1;
+			}
+		} break;
+		case SMBREQ_DISCONNECT :
+		{
+			smbwrp_disconnect(cli);
+		} break;
+		case SMBREQ_OPEN :
+		{
+			if (req->paramlen < sizeof(smbwrp_file))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_open(cli, (smbwrp_file *)req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_CLOSE :
+		{
+			if (req->paramlen < sizeof(smbwrp_file))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_close(cli, (smbwrp_file *)req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_READ :
+		{
+			if (req->paramlen < sizeof(smbwrp_file))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_read(cli, (smbwrp_file *)req->param,
+						data, req->length - req->paramlen, (unsigned long *)&res->value);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_WRITE :
+		{
+			if (req->paramlen < sizeof(smbwrp_file))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_write(cli, (smbwrp_file *)req->param,
+						data, req->length - req->paramlen, (unsigned long *)&res->value);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_LSEEK :
+		{
+			if (req->paramlen < sizeof(smbwrp_file) + sizeof(int) + sizeof(long long))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(int) + sizeof(long long));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_lseek(cli, 
+						(smbwrp_file *)req->param,
+						*(int *)(req->param + sizeof(smbwrp_file)),
+						*(long long *)(req->param + sizeof(smbwrp_file) + sizeof(int)));
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_SETINFO :
+		{
+			if (req->paramlen < sizeof(smbwrp_fileinfo))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_fileinfo));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_setattr(cli, (smbwrp_fileinfo *)req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_GETINFO :
+		{
+			if (req->length < sizeof(smbwrp_fileinfo))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_fileinfo));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_getattr(cli, (smbwrp_fileinfo *)req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_FGETINFO :
+		{
+			if (req->length < sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_fgetattr(cli, 
+						(smbwrp_file *)req->param,
+						(smbwrp_fileinfo *)(req->param + sizeof(smbwrp_file)));
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_FILELIST :
+		{
+			filelist_state state;
+			char * p;
+			if (req->paramlen < sizeof(smbwrp_server) + (CCHMAXPATH + 1))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server) + (CCHMAXPATH + 1));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			state.pipe = pipe;
+			state.bufferlen = req->length - req->paramlen;
+			if (state.bufferlen < sizeof(state))
+			{
+				debuglocal(0,"Not enough buffer to hold data %d\n", state.bufferlen);
+				res->rc = ERROR_BUFFER_OVERFLOW;
+				break;
+			}
+			strncpy(state.mask, req->param + sizeof(smbwrp_server), sizeof(state.mask) - 2);
+			p = getlastslash(state.mask);
+			if (p)
+			{
+				*(p + 1) = '*';
+				*(p + 2) = 0;
+			} 
+			else
+			{
+				strcpy(state.mask, "\\*");
+			}
+			state.data = data;
+			state.datalen = 0;
+			state.add_dir_entry = add_dir_entry;
+			callrc = smbwrp_filelist((smbwrp_server *)req->param, cli, &state);
+			res->rc = maperror(callrc);
+			res->length = state.datalen;
+		} break;
+		case SMBREQ_RENAME :
+		{
+			if (req->paramlen < 2 * (CCHMAXPATH + 1))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, 2 * (CCHMAXPATH + 1));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_rename(cli, req->param,
+						req->param + (CCHMAXPATH + 1));
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_UNLINK :
+		{
+			if (req->paramlen < CCHMAXPATH + 1)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_unlink(cli, req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_MKDIR :
+		{
+			if (req->paramlen < CCHMAXPATH + 1)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_mkdir(cli, req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_RMDIR :
+		{
+			if (req->paramlen < CCHMAXPATH + 1)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_rmdir(cli, req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_CHDIR :
+		{
+			if (req->paramlen < CCHMAXPATH + 1)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_chdir(cli, req->param);
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_NEWSIZE :
+		{
+			if (req->paramlen < sizeof(smbwrp_file) + sizeof(off_t))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(off_t));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_setfilesize(cli, 
+						(smbwrp_file *)req->param,
+						*(off_t *)(req->param + sizeof(smbwrp_file)));
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_SETEA :
+		{
+			// got FEA there
+			FEALIST * pfealist;
+			FEA * pfea;
+			unsigned long done = sizeof(long);
+			if (req->paramlen <  CCHMAXPATH + 1 + sizeof(FEALIST))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + sizeof(FEALIST));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfealist = (FEALIST *)(req->param + CCHMAXPATH + 1);
+			if (req->paramlen < CCHMAXPATH + 1 + pfealist->cbList)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + pfealist->cbList);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfea = pfealist->list;
+			while (done < pfealist->cbList)
+			{
+				callrc = smbwrp_setea(cli, req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
+				if (callrc)
+				{
+					break;
+				}
+				pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
+				done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
+			}
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_FSETEA :
+		{
+			// got FEA there
+			FEALIST * pfealist;
+			FEA * pfea;
+			unsigned long done = sizeof(long);
+			if (req->paramlen <  sizeof(smbwrp_file) + sizeof(FEALIST))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(FEALIST));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfealist = (FEALIST *)(req->param + sizeof(smbwrp_file));
+			if (req->paramlen < sizeof(smbwrp_file) + pfealist->cbList)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + pfealist->cbList);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfea = pfealist->list;
+			while (done < pfealist->cbList)
+			{
+				callrc = smbwrp_fsetea(cli, (smbwrp_file *)req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
+				if (callrc)
+				{
+					break;
+				}
+				pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
+				done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
+			}
+			res->rc = maperror(callrc);
+		} break;
+		case SMBREQ_LISTEA :
+		{
+			FEALIST * pfealist;
+			if (req->paramlen <  CCHMAXPATH + 1)
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfealist = (FEALIST *)data;
+			callrc = smbwrp_listea(cli, req->param, data, req->length);
+			res->rc = maperror(callrc);
+			if (!res->rc && pfealist->cbList > req->length)
+			{
+				res->rc = ERROR_BUFFER_OVERFLOW;
+			}
+		} break;
+		case SMBREQ_FLISTEA :
+		{
+			FEALIST * pfealist;
+			if (req->paramlen <  sizeof(smbwrp_file))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			pfealist = (FEALIST *)data;
+			callrc = smbwrp_flistea(cli, (smbwrp_file *)req->param, data, req->length);
+			res->rc = maperror(callrc);
+			if (!res->rc && pfealist->cbList > req->length)
+			{
+				res->rc = ERROR_BUFFER_OVERFLOW;
+			}
+		} break;
+		case SMBREQ_DSKATTR :
+		{
+			if (req->paramlen <  sizeof(FSALLOCATE))
+			{
+				debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(FSALLOCATE));
+				res->rc = ERROR_INVALID_PARAMETER;
+				break;
+			}
+			callrc = smbwrp_dskattr(cli, (FSALLOCATE*)req->param);
+			res->rc = maperror(callrc);
+			res->length = callrc ? 0 : req->length;
+		} break;
+		default :
+		{
+			debuglocal(0,"Unknown request %d\n", req->request);
+			// rc = ERROR_INVALID_FUNCTION; ??
+			res->rc = ERROR_INVALID_FUNCTION;
+		}
+	}
+	debuglocal(1,"Client request %d rc %d resprc %d resplength %d\n",  req->request, rc, res->rc, res->length);
+	if (res->rc == ERROR_PIPE_NOT_CONNECTED && *reconnect == 1)
+	{
+		debuglocal(1,"Setting reconnect flag\n");
+		*reconnect = 2;
+	}
+	return rc;
+}
+
+void clientthread(void * arg)
+{
+	HPIPE pipe;
+	int rc;
+	smbwrp_server srv = {0};
+	smb_request req = {0};
+	smb_response resp = {0};
+	unsigned long reconnect = 0;
+	unsigned long action;
+	cli_state * cli;
+
+	if (!arg)
+	{
+		debuglocal(0,"Passed null pipe pointer\n");
+		return;
+	}
+	pipe = (HPIPE)arg;
+	rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
+	if (rc)
+	{
+		rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE);
+	}
+	cli = (cli_state *)calloc(smbwrp_getclisize(), 1);
+	if (rc || !cli)
+	{
+		debuglocal(0,"Not enough memory to initialize client structure\n");
+		DosClose(pipe);
+		return;
+	}
+	memset(cli, 0, smbwrp_getclisize());
+	debuglocal(0,"opening client pipe %d\n", pipe);
+	for (;;)
+	{
+		rc = DosRead(pipe, &req, sizeof(req), &action);
+		if (rc || action < sizeof(req))
+		{
+			debuglocal(0,"Failed to read from pipe %d: %d %d\n", pipe, rc, action);
+			break;
+		}
+		// rc = 0 - continue, rc = 1 - quit with response
+		memset(&resp, 0, sizeof(resp));
+		rc = processrequest(pipe, cli, &reconnect, &srv, &req, &resp);
+		if (rc < 2)
+		{
+			rc = DosWrite(pipe, &resp, sizeof(resp), &action);
+			if (rc || action < sizeof(resp))
+			{
+				debuglocal(0,"Failed to write to pipe %d: %d %d\n", pipe, rc, action);
+			}
+		}
+		if (rc)
+		{
+			debuglocal(0,"shutdown client %d with rc %d\n", pipe, rc);
+			break;
+		}
+	}
+	debuglocal(0,"closing client pipe %d\n", pipe);
+	DosDisConnectNPipe(pipe);
+	DosClose(pipe);
+	memset(cli, 0, smbwrp_getclisize());
+	DosFreeMem(cli);
+}
+
+void help(void)
+{
+	printf("Usage: smbcd [-d/--debug <debuglevel>] [-q/--quiet] [-l/--logfile <logfile>]\n");
+}
+
+int main(int argc, char ** argv)
+{
+	int rc = 0, quiet = 0;
+	HPIPE pipe, newpipe;
+	unsigned long action;
+	for (argc--, argv++; argc > 0; argc--, argv++)
+	{
+	 	if (strcmp(argv[0], "-d") == 0 || strcmp(argv[0], "--debug") == 0)
+		{
+			if (argc < 2)
+			{
+				rc = 1;
+				printf("Parameter missing after <%s>", argv[0]);
+				break;
+			}
+			debuglevel = atoi(argv[1]);
+			if (debuglevel <= 0 || debuglevel > 10)
+			{
+				rc = 1;
+				printf("Wrong value <%s> for parameter <%s>", argv[1], argv[0]);
+				break;
+			}
+			if (debuglevel == 10) 
+			{
+				// smbcd crashed on dump_msg used to dump messages on level 10
+				debuglevel--;
+			}
+			argc --;
+			argv ++;
+		} else
+	 	if (strcmp(argv[0], "-l") == 0 || strcmp(argv[0], "--logfile") == 0)
+		{
+			FILE * test;
+			if (argc < 2)
+			{
+				rc = 1;
+				printf("Parameter missing after <%s>", argv[0]);
+				break;
+			}
+			logfile = argv[1];
+			test = fopen(argv[1], "a");
+			if (test == NULL)
+			{
+				rc = 1;
+				printf("Cant open log file <%s>\n", logfile);
+				break;
+			}
+			fclose(test);
+			argc --;
+			argv ++;
+		} else
+	 	if (strcmp(argv[0], "-q") == 0 || strcmp(argv[0], "--quiet") == 0)
+		{
+			quiet = 1;
+		} else
+		{
+			printf("Unknown parameter <%s>\n", argv[0]);
+			rc = 1;
+			break;
+		}
+	}
+	if (rc)
+	{
+		help();
+		return 1;
+	}
+	if (quiet)
+	{
+		debuglevel = -10;
+	}
+	rc = DosCreateMutexSem(NULL, &logmutex, 0, 0);
+	if (rc)
+	{
+		if (!quiet) printf("DosCreateMutexSem %d\n", rc);
+		return 1;
+	}
+	rc = smbwrp_init();
+	if (rc)
+	{
+		debuglocal(0,"Init failed with rc %d\n", rc);
+		return 1;
+	}
+	rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
+	if (rc == NO_ERROR)
+	{
+		debuglocal(0,"Pipe %s already exists. May be duplicate smbcd is running\n", PIPENAME);
+		DosClose(pipe);
+		return 1;		
+	}
+
+	rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
+				NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
+				600, 600, 1000);
+	if (rc)
+	{
+		debuglocal(0,"Cant create named pipe %d\n", rc);
+		return 1;
+	}
+
+	debuglocal(1,"Entering main loop. My pid is %d. My mutex is %08x. My debuglevel is %d. Client state size %d\n", getpid(), logmutex, debuglevel, smbwrp_getclisize());
+
+	for (;;)
+	{
+		do
+		{
+			rc = DosConnectNPipe(pipe);
+		} while (rc == ERROR_INTERRUPT);
+
+		if (!rc)
+		{
+			debuglocal(1,"New client connected %d to pipe %d\n", rc, pipe);
+			int tid = _beginthread(clientthread, NULL, 655360, (void *)pipe);
+			if (tid < 0)
+			{
+				debuglocal(0,"Failed to create client thread\n");
+				rc = 0xFFFF;
+			}
+		}
+
+		if (rc)
+		{
+			debuglocal(0,"Client failed to connect %d\n", rc);
+			DosDisConnectNPipe(pipe);
+			DosClose(pipe);
+		}
+		
+		rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
+				NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
+				600, 600, 1000);
+		if (rc)
+		{
+			debuglocal(0,"Cant create new named pipe %d\n", rc);
+			break;
+		}
+	}
+
+	DosDisConnectNPipe(pipe);
+	DosClose(pipe);
+	DosCloseMutexSem(logmutex);
+	return 0;
+}
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.h	(revision 5)
@@ -0,0 +1,51 @@
+#ifndef _SMBCD_H
+#define _SMBCD_H
+
+#define PIPENAME "\\PIPE\\NICKK\\SMBCD"
+#define EXECNAME "smbcd.exe"
+
+#define SMBREQ_INIT		1
+#define SMBREQ_INITCOMPLETE	2
+#define SMBREQ_CONNECT		3
+#define SMBREQ_DISCONNECT	4
+#define SMBREQ_OPEN		5
+#define SMBREQ_CLOSE		6
+#define SMBREQ_READ		7
+#define SMBREQ_WRITE		8
+#define SMBREQ_LSEEK		9
+#define SMBREQ_SETINFO		10
+#define SMBREQ_GETINFO		11
+#define SMBREQ_FGETINFO		12
+#define SMBREQ_FILELIST		13
+#define SMBREQ_RENAME		14
+#define SMBREQ_UNLINK		15
+#define SMBREQ_MKDIR		16
+#define SMBREQ_RMDIR		17
+#define SMBREQ_CHDIR		18
+#define SMBREQ_NEWSIZE		19
+#define SMBREQ_SETEA		20
+#define SMBREQ_FSETEA		21
+#define SMBREQ_LISTEA		22
+#define SMBREQ_FLISTEA		23
+#define SMBREQ_DSKATTR		24
+
+#pragma pack(1)
+
+typedef struct smb_request
+{
+	int request;
+	char * param;
+	int paramlen;
+	int length;
+} smb_request;
+
+typedef struct smb_response
+{
+	int rc;
+	unsigned long long value;
+	int length;
+} smb_response;
+
+#pragma pack()
+
+#endif /* _SMBCD_H */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.c	(revision 5)
@@ -0,0 +1,1523 @@
+#include "includes.h"
+
+#include "smbwrp.h"
+
+/*
+ * Wrapper for cli_errno to return not connected error on negative fd
+ */
+int os2cli_errno(cli_state * cli)
+{
+	if (cli->fd == -1)
+	{
+		return ENOTCONN;
+	}
+	return cli_errno(cli);
+}
+
+int _System smbwrp_getclisize(void)
+{
+	return sizeof(struct cli_state);
+}
+
+/***************************************************** 
+initialise structures
+*******************************************************/
+int _System smbwrp_init(void)
+{
+	static int initialised = 0;
+	char *p;
+	pstring line;
+
+	if (initialised) 
+	{
+		return 0;
+	}
+	initialised = 1;
+
+	init_globals();
+
+	load_interfaces();
+
+	if (!init_names())
+	{
+		return 1;
+	}
+
+/*
+	if ((p=smbw_getshared("RESOLVE_ORDER"))) {
+		lp_set_name_resolve_order(p);
+	}
+*/
+	return 0;
+
+}
+
+#if 0
+/***************************************************** 
+remove redundent stuff from a filename
+*******************************************************/
+void clean_fname(char *name)
+{
+	char *p, *p2;
+	int l;
+	int modified = 1;
+
+	if (!name) return;
+
+	while (modified) {
+		modified = 0;
+
+		if ((p=strstr(name,"/./"))) {
+			modified = 1;
+			while (*p) {
+				p[0] = p[2];
+				p++;
+			}
+		}
+
+		if ((p=strstr(name,"//"))) {
+			modified = 1;
+			while (*p) {
+				p[0] = p[1];
+				p++;
+			}
+		}
+
+		if (strcmp(name,"/../")==0) {
+			modified = 1;
+			name[1] = 0;
+		}
+
+		if ((p=strstr(name,"/../"))) {
+			modified = 1;
+			for (p2=(p>name?p-1:p);p2>name;p2--) {
+				if (p2[0] == '/') break;
+			}
+			while (*p2) {
+				p2[0] = p2[3];
+				p2++;
+			}
+		}
+
+		if (strcmp(name,"/..")==0) {
+			modified = 1;
+			name[1] = 0;
+		}
+
+		l = strlen(name);
+		p = l>=3?(name+l-3):name;
+		if (strcmp(p,"/..")==0) {
+			modified = 1;
+			for (p2=p-1;p2>name;p2--) {
+				if (p2[0] == '/') break;
+			}
+			if (p2==name) {
+				p[0] = '/';
+				p[1] = 0;
+			} else {
+				p2[0] = 0;
+			}
+		}
+
+		l = strlen(name);
+		p = l>=2?(name+l-2):name;
+		if (strcmp(p,"/.")==0) {
+			if (p == name) {
+				p[1] = 0;
+			} else {
+				p[0] = 0;
+			}
+		}
+
+		if (strncmp(p=name,"./",2) == 0) {      
+			modified = 1;
+			do {
+				p[0] = p[2];
+			} while (*p++);
+		}
+
+		l = strlen(p=name);
+		if (l > 1 && p[l-1] == '/') {
+			modified = 1;
+			p[l-1] = 0;
+		}
+	}
+}
+#endif
+
+
+/****************************************************************************
+send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
+****************************************************************************/
+BOOL cli_qpathinfo3(struct cli_state *cli, const char *fname, 
+		    time_t *c_time, time_t *a_time, time_t *m_time, 
+		    time_t *w_time, off_t *size, uint16 *mode,
+		    SMB_INO_T *ino)
+{
+	unsigned int data_len = 0;
+	unsigned int param_len = 0;
+	uint16 setup = TRANSACT2_QPATHINFO;
+	pstring param;
+	char *rparam=NULL, *rdata=NULL;
+	char *p;
+
+	p = param;
+	memset(p, 0, 6);
+	SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
+	p += 6;
+	p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
+
+	param_len = PTR_DIFF(p, param);
+
+	if (!cli_send_trans(cli, SMBtrans2, 
+                            NULL,                         /* name */
+                            -1, 0,                        /* fid, flags */
+                            &setup, 1, 0,                 /* setup, length, max */
+                            param, param_len, 10,         /* param, length, max */
+                            NULL, data_len, cli->max_xmit /* data, length, max */
+                           )) {
+		return False;
+	}
+
+	if (!cli_receive_trans(cli, SMBtrans2,
+                               &rparam, &param_len,
+                               &rdata, &data_len)) {
+		return False;
+	}
+
+	if (!rdata || data_len < 22) {
+		return False;
+	}
+
+	if (c_time) {
+		*c_time = interpret_long_date(rdata+0) - cli->serverzone;
+	}
+	if (a_time) {
+		*a_time = interpret_long_date(rdata+8) - cli->serverzone;
+	}
+	if (m_time) {
+		*m_time = interpret_long_date(rdata+16) - cli->serverzone;
+	}
+	if (w_time) {
+		*w_time = interpret_long_date(rdata+24) - cli->serverzone;
+	}
+	if (mode) {
+		*mode = SVAL(rdata, 32);
+	}
+	if (size) {
+		*size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
+	}
+	if (ino) {
+		*ino = IVAL(rdata, 64);
+	}
+
+	SAFE_FREE(rdata);
+	SAFE_FREE(rparam);
+	return True;
+}
+
+/****************************************************************************
+send a qfileinfo call
+****************************************************************************/
+BOOL cli_qfileinfo3(struct cli_state *cli, int fnum, 
+		   uint16 *mode, off_t *size,
+		   time_t *c_time, time_t *a_time, time_t *m_time, 
+		   time_t *w_time, SMB_INO_T *ino)
+{
+	unsigned int data_len = 0;
+	unsigned int param_len = 0;
+	uint16 setup = TRANSACT2_QFILEINFO;
+	pstring param;
+	char *rparam=NULL, *rdata=NULL;
+
+	/* if its a win95 server then fail this - win95 totally screws it
+	   up */
+	if (cli->win95) return False;
+
+	param_len = 4;
+
+	memset(param, 0, param_len);
+	SSVAL(param, 0, fnum);
+	SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
+
+	if (!cli_send_trans(cli, SMBtrans2, 
+                            NULL,                           /* name */
+                            -1, 0,                          /* fid, flags */
+                            &setup, 1, 0,                   /* setup, length, max */
+                            param, param_len, 2,            /* param, length, max */
+                            NULL, data_len, cli->max_xmit   /* data, length, max */
+                           )) {
+		return False;
+	}
+
+	if (!cli_receive_trans(cli, SMBtrans2,
+                               &rparam, &param_len,
+                               &rdata, &data_len)) {
+		return False;
+	}
+
+	if (!rdata || data_len < 68) {
+		return False;
+	}
+
+	if (c_time) {
+		*c_time = interpret_long_date(rdata+0) - cli->serverzone;
+	}
+	if (a_time) {
+		*a_time = interpret_long_date(rdata+8) - cli->serverzone;
+	}
+	if (m_time) {
+		*m_time = interpret_long_date(rdata+16) - cli->serverzone;
+	}
+	if (w_time) {
+		*w_time = interpret_long_date(rdata+24) - cli->serverzone;
+	}
+	if (mode) {
+		*mode = SVAL(rdata, 32);
+	}
+	if (size) {
+		*size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
+	}
+	if (ino) {
+		*ino = IVAL(rdata, 64);
+	}
+
+	SAFE_FREE(rdata);
+	SAFE_FREE(rparam);
+	return True;
+}
+
+/***************************************************** 
+return a connection to a server
+*******************************************************/
+int _System smbwrp_connect(smbwrp_server * srv, cli_state * c)
+{
+	char * server = srv->server_name;
+	char * share = *(srv->share_name) ? srv->share_name : "IPC$";
+	char * workgroup = srv->workgroup;
+	struct nmb_name called, calling;
+	char *p, *server_n = server;
+	fstring group;
+	struct in_addr ip;
+	int rc;
+
+        zero_ip(&ip);
+	ZERO_STRUCTP(c);
+
+	DEBUG(1,("Connecting to \\\\%s:%s@%s:%s\\%s. Master %s:%d\n", srv->username, srv->password, workgroup, server, share, srv->master, srv->ifmastergroup));
+
+	if (!*server) {
+		struct in_addr sip;
+
+		if (*workgroup)
+		{
+			if (!find_master_ip(workgroup, &sip)) {
+				return 1;
+			}
+			fstrcpy(group, inet_ntoa(sip));
+			server_n = group;
+		} else
+		if (*srv->master)
+		{
+			if (srv->ifmastergroup)
+			{
+				if (!find_master_ip(srv->master, &sip)) {
+					return 11;
+				}
+				strncpy(srv->master, inet_ntoa(sip), sizeof(srv->master) - 1);
+				srv->ifmastergroup = 0;
+			}
+			server_n = srv->master;
+		} else
+		{
+			return 10;
+		}		
+	}
+
+	make_nmb_name(&calling, global_myname(), 0x0);
+//	make_nmb_name(&calling, "WORK", 0x0); // this machine name
+	make_nmb_name(&called , server_n, 0x20);
+
+ again:
+        zero_ip(&ip);
+
+	/* have to open a new connection */
+	if (!cli_initialise(c))
+	{
+		return 2;
+	}
+
+	if (!cli_connect(c, server_n, &ip)) 
+	{
+		return 3;
+	}
+	if (!cli_session_request(c, &calling, &called)) {
+		cli_shutdown(c);
+		if (strcmp(called.name, "*SMBSERVER")) {
+			make_nmb_name(&called , "*SMBSERVER", 0x20);
+			goto again;
+		}
+		return 4;
+	}
+
+	DEBUG(4,(" session request ok\n"));
+
+	if (!cli_negprot(c)) {
+		cli_shutdown(c);
+		return 5;
+	}
+
+	DEBUG(4,(" session setuping for <%s>/<%s> %d in <%s> %08x %08x %08x\n", srv->username, srv->password, strlen(srv->password), workgroup, c->protocol, c->sec_mode, c->capabilities));
+
+	rc = cli_session_setup(c, srv->username, 
+			       srv->password, strlen(srv->password),
+			       srv->password, strlen(srv->password),
+			       workgroup);
+	if (!rc)
+	{
+		DEBUG(4,("%s/%s login failed\n", srv->username, srv->password));
+		/* try an anonymous login if it failed */
+		rc = cli_session_setup(c, "", "", 1,"", 0, workgroup);
+		if (!rc)
+		{
+			DEBUG(4,("Anonymous login failed"));
+			cli_shutdown(c);
+			return 6;
+		}
+	}
+
+	DEBUG(4,(" session setup ok. Sending tconx <%s> <%s> %d\n", share, srv->password, strlen(srv->password)));
+
+	if (!cli_send_tconX(c, share, "?????",
+			    srv->password, strlen(srv->password)+1)) {
+		cli_shutdown(c);
+		return 7;
+	}
+
+	DEBUG(4,(" tconx ok. cli caps %08x\n", c->capabilities));
+
+//	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
+
+	return 0;
+}
+
+/***************************************************** 
+close a connection to a server
+*******************************************************/
+void _System smbwrp_disconnect(cli_state * cli)
+{
+	if (cli)
+	{
+		cli_shutdown(cli);
+	}
+}
+
+
+
+/***************************************************** 
+a wrapper for open()
+*******************************************************/
+int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
+{
+	int fd = -1;
+
+	if (!cli || !file || !*file->fname) 
+	{
+		return EINVAL;
+	}
+	if (file->denymode < DENY_ALL || file->denymode > DENY_NONE) 
+	{
+		file->denymode = DENY_NONE;
+	}
+
+	DEBUG(4,("cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode));
+	file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
+	if (file->fd == -1)
+	{	
+		return os2cli_errno(cli);
+	}
+	if (file->openmode & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))
+	{
+		time_t t;
+		file->mtime = time(NULL);
+		t = TimeDiff(file->mtime);
+		DEBUG(4,("cli_open mtime %lu %lu\n", file->mtime, t));
+		file->mtime -= t;
+	}
+	file->offset = 0;
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for read()
+*******************************************************/
+int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
+{
+	int ret;
+
+	if (!cli || !file || !buf || !result) 
+	{
+		return EINVAL;
+	}
+	
+	*result = 0;
+	ret = cli_read(cli, file->fd, buf, file->offset, count);
+	if (ret == -1) 
+	{
+		return os2cli_errno(cli);
+	}
+
+	file->offset += ret;
+	*result = ret;
+	return 0;	
+}
+
+	
+
+/***************************************************** 
+a wrapper for write()
+*******************************************************/
+int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
+{
+	int ret;
+
+	if (!cli || !file || !buf || !result) 
+	{
+		return EINVAL;
+	}
+	
+	*result = 0;
+//DEBUG(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
+	ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
+	if (ret == -1) 
+	{
+		return os2cli_errno(cli);
+	}
+
+	file->offset += ret;
+	*result = ret;
+	return 0;	
+}
+
+/***************************************************** 
+a wrapper for close()
+*******************************************************/
+int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
+{
+	int rc = 0;
+	if (!cli || !file) 
+	{
+		return EINVAL;
+	}
+
+	
+	if (!cli_close(cli, file->fd))
+	{
+		return os2cli_errno(cli);
+	}
+	file->fd = -1;
+	file->offset = 0;
+	if (file->openattr || file->mtime)
+	{
+		DEBUG(4,("Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime + TimeDiff(file->mtime)));
+		if (!cli_setatr(cli, file->fname, file->openattr, file->mtime + TimeDiff(file->mtime))) 
+		{
+			DEBUG(4,("Set attr on close failed %d\n", os2cli_errno(cli)));
+			//rc = os2cli_errno(cli);
+		}	
+		file->openattr = 0;
+		file->mtime = 0;
+	}
+	*file->fname = 0;
+	return rc;
+}
+
+/***************************************************** 
+a wrapper for setfilesize()
+*******************************************************/
+int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
+{
+	unsigned int data_len = 8;
+	unsigned int param_len = 6;
+	uint16 setup = TRANSACT2_SETFILEINFO;
+	pstring param;
+	char *rparam=NULL, *rdata=NULL;
+
+	memset(param, 0, param_len);
+	SSVAL(param,0,fnum);
+	SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
+
+	if (!cli_send_trans(cli, SMBtrans2,
+						NULL,                        /* name */
+						-1, 0,                          /* fid, flags */
+						&setup, 1, 0,                   /* setup, length, max */
+						param, param_len, 2,            /* param, length, max */
+						(char *)&newsize,  sizeof(newsize), cli->max_xmit /* data, length, max */
+						)) {
+		return False;
+	}
+
+	if (!cli_receive_trans(cli, SMBtrans2,
+						&rparam, &param_len,
+						&rdata, &data_len)) {
+		return False;
+	}
+
+	SAFE_FREE(rdata);
+	SAFE_FREE(rparam);
+
+	return True;
+}
+
+int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
+{
+	int rc = 0;
+	if (!cli || !file) 
+	{
+		return EINVAL;
+	}
+
+	DEBUG(4,("cli_setnewfileszie(%s) %lld\n", file->fname, newsize));
+	if (!cli_setfilenewsize(cli, file->fd, newsize))
+	{
+		if (newsize)
+		{
+			rc = os2cli_errno(cli);
+		}
+
+		if (!cli_close(cli, file->fd))
+		{
+			return os2cli_errno(cli);
+		}
+		file->fd = -1;
+		file->offset = 0;			
+		file->openmode &= ~(O_CREAT | O_EXCL);
+		file->openmode |= O_TRUNC;
+		DEBUG(4,("cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode));
+		file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
+		if (file->fd == -1)
+		{	
+			return os2cli_errno(cli);
+		}
+	}	
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for rename()
+*******************************************************/
+int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
+{
+	if (!cli || !oldname || !newname) 
+	{
+		return EINVAL;
+	}
+
+	DEBUG(1,("Rename <%s> -> <%s>\n", oldname, newname));
+	//cli_unlink(cli, newname);
+//	if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname)) 
+	if (!cli_rename(cli, oldname, newname)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+
+/***************************************************** 
+a wrapper for chmod()
+*******************************************************/
+int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
+{
+	if (!cli || !finfo || !*finfo->fname) 
+	{
+		return EINVAL;
+	}
+
+DEBUG(4,("Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + TimeDiff(finfo->mtime)));
+	if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : TimeDiff(finfo->mtime)))
+		&& !cli_setatr(cli, finfo->fname, finfo->attr, 0)) 
+	{
+		return os2cli_errno(cli);
+	}	
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for unlink()
+*******************************************************/
+int _System smbwrp_unlink(cli_state * cli, const char *fname)
+{
+	if (!cli || !fname) 
+	{
+		return EINVAL;
+	}
+#if 0
+	if (strncmp(cli->dev, "LPT", 3) == 0) 
+	{
+		int job = smbw_stat_printjob(cli, fname, NULL, NULL);
+		if (job == -1) 
+		{
+			goto failed;
+		}
+		if (cli_printjob_del(cli, job) != 0) 
+		{
+			goto failed;
+		}
+	} else 
+#endif
+	if (!cli_unlink(cli, fname)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for lseek()
+*******************************************************/
+int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
+{
+	off_t size;
+	if (!cli || !file) 
+	{
+		return EINVAL;
+	}
+
+	DEBUG(4,("lseek %d %lld %lld\n", whence, offset, file->offset));
+
+	switch (whence) {
+	case SEEK_SET:
+		if (offset < 0)
+		{
+			return EINVAL;
+		}
+		file->offset = offset;
+		break;
+	case SEEK_CUR:
+		file->offset += offset;
+		break;
+	case SEEK_END:
+		if (offset > 0)
+		{
+			return EINVAL;
+		}
+		if (!cli_qfileinfo3(cli, file->fd, 
+				   NULL, &size, NULL, NULL, NULL, 
+				   NULL, NULL) &&
+		    !cli_getattrE(cli, file->fd, 
+				  NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL)) 
+		{
+			return os2cli_errno(cli);
+		}
+		file->offset = size + offset;
+		break;
+	default: return EINVAL;
+	}
+
+	return 0;
+}
+
+/***************************************************** 
+try to do a QPATHINFO and if that fails then do a getatr
+this is needed because win95 sometimes refuses the qpathinfo
+*******************************************************/
+int _System smbwrp_getattr(cli_state * cli, smbwrp_fileinfo *finfo)
+{
+	SMB_INO_T ino = 0;
+	if (!cli || !finfo || !*finfo->fname) 
+	{
+		return EINVAL;
+	}
+	DEBUG(4,("getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname));
+	if (!(cli->capabilities & CAP_NOPATHINFO2) &&
+		cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
+			   (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
+	{
+		finfo->attr &= 0x7F;
+//DEBUG(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
+//		finfo->ctime -= TimeDiff(finfo->ctime);
+//		finfo->atime -= TimeDiff(finfo->atime);
+//		finfo->mtime -= TimeDiff(finfo->mtime);
+		return 0;
+	}
+//DEBUG(2,("getattr rc1 %d\n", os2cli_errno(cli)));
+
+	/* if this is NT then don't bother with the getatr */
+	if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2)) 
+	{
+		int rc = os2cli_errno(cli);
+		// cli_qpathinfo* reports EINVAL when path of given file not exists
+		// thus there is no real situation when EINVAL should be returned to 
+		// client at this point, we just replace it to ENOTDIR
+		if (rc == EINVAL)
+		{
+			rc = ENOTDIR;
+		}
+		return rc;
+	}
+
+	if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, (size_t *)&finfo->size, (time_t *)&finfo->mtime)) 
+	{
+//DEBUG(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
+		finfo->mtime -= TimeDiff(finfo->mtime);
+		finfo->atime = finfo->mtime;
+		finfo->ctime = finfo->mtime;
+		cli->capabilities &= CAP_NOPATHINFO2;
+		return 0;
+	}
+	return os2cli_errno(cli);
+}
+
+/***************************************************** 
+try to do a QPATHINFO and if that fails then do a getatr
+this is needed because win95 sometimes refuses the qpathinfo
+*******************************************************/
+int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
+{
+	SMB_INO_T ino = 0;
+	if (!cli || !file || !finfo) 
+	{
+		return EINVAL;
+	}
+
+	strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
+	if (!cli_qfileinfo3(cli, file->fd, 
+			   (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
+			   &ino))
+	{
+		if (!cli_getattrE(cli, file->fd, 
+			  (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)) 
+		{
+			return os2cli_errno(cli);
+		}
+		else
+		{
+			finfo->ctime -= TimeDiff(finfo->ctime);
+			finfo->atime -= TimeDiff(finfo->atime);
+			finfo->mtime -= TimeDiff(finfo->mtime);
+		}
+	}
+	else
+	{
+//		finfo->ctime -= TimeDiff(finfo->ctime);
+//		finfo->atime -= TimeDiff(finfo->atime);
+//		finfo->mtime -= TimeDiff(finfo->mtime);
+	}
+
+	return 0;
+}
+
+// =============================DIRECTORY ROUTINES============================
+
+/***************************************************** 
+add a entry to a directory listing
+*******************************************************/
+static void smbwrp_dir_add(smbwrp_fileinfo *finfo, const char *mask, void *state)
+{
+	if (state && finfo)
+	{
+		filelist_state * st  = (filelist_state *)state;
+		if (st->add_dir_entry)
+		{
+DEBUG(8,("adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen));
+			memcpy(&st->finfo, finfo, sizeof(st->finfo));
+			st->add_dir_entry(state);
+		}
+	}
+}
+
+static void smbwrp_dir_add_old(struct file_info *finfo, const char *mask, void *state)
+{
+	if (state && finfo)
+	{
+		filelist_state * st  = (filelist_state *)state;
+		if (st->add_dir_entry)
+		{
+			strncpy(st->finfo.fname, finfo->name, sizeof(st->finfo.fname) - 1);
+			st->finfo.size = finfo->size;
+			st->finfo.easize = -1;
+			st->finfo.attr = finfo->mode;
+			st->finfo.ctime = finfo->ctime - TimeDiff(finfo->ctime);
+			st->finfo.mtime = finfo->mtime - TimeDiff(finfo->mtime);
+			st->finfo.atime = finfo->atime - TimeDiff(finfo->atime);
+			st->add_dir_entry(state);
+		}
+	}
+}
+
+static void smbwrp_special_add(char * name, void * state)
+{
+	smbwrp_fileinfo finfo = {0};
+
+	if (!name)
+	{
+		return;
+	}
+
+	ZERO_STRUCT(finfo);
+
+	strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
+	finfo.attr = aRONLY | aDIR;
+
+	smbwrp_dir_add(&finfo, NULL, state);
+}
+
+static void smbwrp_printjob_add(struct print_job_info *job, void * state)
+{
+	smbwrp_fileinfo finfo = {0};
+
+	ZERO_STRUCT(finfo);
+
+//printf("Printjob <%s>\n", job->name);
+
+	strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
+	finfo.mtime = job->t - TimeDiff(job->t);
+	finfo.atime = finfo.mtime;
+	finfo.ctime = finfo.mtime;
+	finfo.attr = aRONLY;
+	finfo.size = job->size;
+
+	smbwrp_dir_add(&finfo, NULL, state);
+}
+
+static void smbwrp_share_add(const char *share, uint32 type, 
+			   const char *comment, void *state)
+{
+	smbwrp_fileinfo finfo = {0};
+
+	if (strcmp(share,"IPC$") == 0) return;
+
+	ZERO_STRUCT(finfo);
+
+	strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
+	finfo.attr = aRONLY | aDIR;	
+
+	smbwrp_dir_add(&finfo, NULL, state);
+}
+
+
+/****************************************************************************
+ Interpret a long filename structure - this is mostly guesses at the moment.
+ The length of the structure is returned
+ The structure of a long filename depends on the info level. 260 is used
+ by NT and 2 is used by OS/2
+****************************************************************************/
+
+static int interpret_long_filename(struct cli_state *cli,
+				   int level,char *p,smbwrp_fileinfo *finfo)
+{
+	extern file_info def_finfo;
+	int len;
+	char *base = p;
+	smbwrp_fileinfo finfo1;
+	
+	if (!finfo) finfo = &finfo1;
+
+//	memcpy(finfo,&def_finfo,sizeof(*finfo));
+	finfo->attr = def_finfo.mode;
+	finfo->mtime = def_finfo.mtime;
+	finfo->atime = def_finfo.atime;
+	finfo->ctime = def_finfo.ctime;
+	strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
+
+	switch (level) {
+		case 1: /* OS/2 understands this */
+			/* these dates are converted to GMT by
+                           make_unix_date */
+			finfo->ctime = make_unix_date2(p+4);
+			finfo->atime = make_unix_date2(p+8);
+			finfo->mtime = make_unix_date2(p+12);
+			finfo->size = IVAL(p,16);
+			finfo->attr = CVAL(p,24);
+			len = CVAL(p, 26);
+			p += 27;
+			p += clistr_align_in(cli, p, 0);
+			/* the len+2 below looks strange but it is
+			   important to cope with the differences
+			   between win2000 and win9x for this call
+			   (tridge) */
+			p += clistr_pull(cli, finfo->fname, p,
+					 sizeof(finfo->fname),
+					 len+2, 
+					 STR_TERMINATE);
+			finfo->easize = -1;
+			return PTR_DIFF(p, base);
+
+		case 2: /* this is what OS/2 uses mostly */
+			/* these dates are converted to GMT by
+                           make_unix_date */
+			finfo->ctime = make_unix_date2(p+4);
+			finfo->atime = make_unix_date2(p+8);
+			finfo->mtime = make_unix_date2(p+12);
+			finfo->size = IVAL(p,16);
+			finfo->attr = CVAL(p,24);
+			finfo->easize = IVAL(p,26);
+			len = CVAL(p, 30);
+			p += 31;
+			/* check for unisys! */
+			p += clistr_pull(cli, finfo->fname, p,
+					 sizeof(finfo->fname),
+					 len, 
+					 STR_NOALIGN);
+			return PTR_DIFF(p, base) + 1;
+			
+		case 260: /* NT uses this, but also accepts 2 */
+		{
+			size_t namelen, slen;
+			p += 4; /* next entry offset */
+			p += 4; /* fileindex */
+				
+			/* these dates appear to arrive in a
+			   weird way. It seems to be localtime
+			   plus the serverzone given in the
+			   initial connect. This is GMT when
+			   DST is not in effect and one hour
+			   from GMT otherwise. Can this really
+			   be right??
+			   
+			   I suppose this could be called
+			   kludge-GMT. Is is the GMT you get
+			   by using the current DST setting on
+			   a different localtime. It will be
+			   cheap to calculate, I suppose, as
+			   no DST tables will be needed */
+			
+			finfo->ctime = interpret_long_date(p);
+			p += 8;
+			finfo->atime = interpret_long_date(p);
+			p += 8;
+			finfo->mtime = interpret_long_date(p);
+			p += 8;
+			p += 8;
+			finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
+			p += 8;
+			p += 8; /* alloc size */
+			finfo->attr = CVAL(p,0);
+			p += 4;
+			namelen = IVAL(p,0);
+			p += 4;
+			finfo->easize = IVAL(p,0);
+			p += 4; /* EA size */
+			slen = SVAL(p, 0);
+			p += 2; 
+			p += 24; /* short name? */	  
+			clistr_pull(cli, finfo->fname, p,
+				    sizeof(finfo->fname),
+				    namelen, 0);
+			return SVAL(base, 0);
+		}
+	}
+	
+	DEBUG(1,("Unknown long filename format %d\n",level));
+	return(SVAL(p,0));
+}
+
+/****************************************************************************
+ Do a directory listing, calling fn on each file found.
+ Modified from cli_list_new
+****************************************************************************/
+
+static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute, 
+		 void (*fn)(smbwrp_fileinfo *, const char *, void *), void *state)
+{
+	int max_matches = 512;
+	int info_level;
+	char *p, *p2;
+	pstring mask;
+	smbwrp_fileinfo finfo;
+	int i;
+	char *tdl, *dirlist = NULL;
+	int dirlist_len = 0;
+	int total_received = -1;
+	BOOL First = True;
+	int ff_searchcount=0;
+	int ff_eos=0;
+	int ff_lastname=0;
+	int ff_dir_handle=0;
+	int loop_count = 0;
+	char *rparam=NULL, *rdata=NULL;
+	unsigned int param_len, data_len;	
+	uint16 setup;
+	pstring param;
+
+	/* NT uses 260, OS/2 uses 2. Both accept 1. */
+	info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
+
+	DEBUG(4,("list_files level %d. mask <%s>\n", info_level, mask));
+
+	pstrcpy(mask,Mask);
+	
+	while (ff_eos == 0) {
+		loop_count++;
+		if (loop_count > 200) {
+			DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
+			break;
+		}
+
+		if (First) {
+			setup = TRANSACT2_FINDFIRST;
+			SSVAL(param,0,attribute); /* attribute */
+			SSVAL(param,2,max_matches); /* max count */
+			SSVAL(param,4,4+2);	/* resume required + close on end */
+			SSVAL(param,6,info_level); 
+			SIVAL(param,8,0);
+			p = param+12;
+			p += clistr_push(cli, param+12, mask, sizeof(param)-12, 
+					 STR_TERMINATE);
+		} else {
+			setup = TRANSACT2_FINDNEXT;
+			SSVAL(param,0,ff_dir_handle);
+			SSVAL(param,2,max_matches); /* max count */
+			SSVAL(param,4,info_level); 
+			SIVAL(param,6,0); /* ff_resume_key */
+			SSVAL(param,10,8+4+2);	/* continue + resume required + close on end */
+			p = param+12;
+			p += clistr_push(cli, param+12, mask, sizeof(param)-12, 
+					 STR_TERMINATE);
+		}
+
+		param_len = PTR_DIFF(p, param);
+		if (!cli_send_trans(cli, SMBtrans2, 
+				    NULL,                   /* Name */
+				    -1, 0,                  /* fid, flags */
+				    &setup, 1, 0,           /* setup, length, max */
+				    param, param_len, 10,   /* param, length, max */
+				    NULL, 0, 
+#if 0
+				    /* w2k value. */
+				    MIN(16384,cli->max_xmit) /* data, length, max. */
+#else
+				    cli->max_xmit	    /* data, length, max. */
+#endif
+				    )) {
+			break;
+		}
+
+		if (!cli_receive_trans(cli, SMBtrans2, 
+				       &rparam, &param_len,
+				       &rdata, &data_len) &&
+                    cli_is_dos_error(cli)) {
+			/* we need to work around a Win95 bug - sometimes
+			   it gives ERRSRV/ERRerror temprarily */
+			uint8 eclass;
+			uint32 ecode;
+			cli_dos_error(cli, &eclass, &ecode);
+			if (eclass != ERRSRV || ecode != ERRerror)
+				break;
+			smb_msleep(100);
+			continue;
+		}
+
+
+                if (cli_is_error(cli) || !rdata || !rparam) 
+		{
+			if (First && info_level == 2)
+			{
+				// we have tried query ea size, but now will try without ea size
+				info_level = 1;
+				DEBUG(4,("list_files fallback to level %d\n", info_level));
+				continue;
+			}
+			break;
+		}
+
+		if (total_received == -1)
+			total_received = 0;
+
+		/* parse out some important return info */
+		p = rparam;
+		if (First) {
+			ff_dir_handle = SVAL(p,0);
+			ff_searchcount = SVAL(p,2);
+			ff_eos = SVAL(p,4);
+			ff_lastname = SVAL(p,8);
+		} else {
+			ff_searchcount = SVAL(p,0);
+			ff_eos = SVAL(p,2);
+			ff_lastname = SVAL(p,6);
+		}
+		DEBUG(4,("list_files %d %d %d %d\n", ff_searchcount, ff_eos, ff_lastname, First));
+
+		if (ff_searchcount == 0) 
+			break;
+
+		/* point to the data bytes */
+		p = rdata;
+
+		memset(&finfo, 0, sizeof(finfo));
+		finfo.easize = -1;
+		/* we might need the lastname for continuations */
+		if (ff_lastname > 0) {
+			switch(info_level) {
+				case 260:
+					clistr_pull(cli, mask, p+ff_lastname,
+						    sizeof(mask), 
+						    data_len-ff_lastname,
+						    STR_TERMINATE);
+					break;
+				case 1:
+				case 2:
+					clistr_pull(cli, mask, p+ff_lastname+1,
+						    sizeof(mask), 
+						    -1,
+						    STR_TERMINATE);
+					break;
+				}
+		} else {
+			pstrcpy(mask,"");
+		}
+ 
+		/* and add them to the dirlist pool */
+		tdl = Realloc(dirlist,dirlist_len + data_len);
+
+		if (!tdl) {
+			DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
+			break;
+		} else {
+			dirlist = tdl;
+		}
+
+		/* put in a length for the last entry, to ensure we can chain entries 
+		   into the next packet */
+		for (p2=p,i=0;i<(ff_searchcount-1);i++)
+			p2 += interpret_long_filename(cli,info_level,p2,NULL);
+		SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
+
+		/* grab the data for later use */
+		memcpy(dirlist+dirlist_len,p,data_len);
+		dirlist_len += data_len;
+
+		total_received += ff_searchcount;
+
+		SAFE_FREE(rdata);
+		SAFE_FREE(rparam);
+
+		DEBUG(3,("received %d entries (eos=%d)\n",
+			 ff_searchcount,ff_eos));
+
+		if (ff_searchcount > 0)
+			loop_count = 0;
+
+		First = False;
+	}
+
+	DEBUG(3,("total received %d entries\n", total_received));
+	for (p=dirlist,i=0;i<total_received;i++) {
+		p += interpret_long_filename(cli,info_level,p,&finfo);
+		fn(&finfo, Mask, state);
+	}
+
+	/* free up the dirlist buffer */
+	SAFE_FREE(dirlist);
+	return(total_received);
+}
+
+
+/***************************************************** 
+open a directory on the server
+*******************************************************/
+int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
+{
+	if (!srv || !cli || !state || !*state->mask)
+	{
+		return EINVAL;
+	}
+	DEBUG(1,("Filelist <%s> on master <%s> wgrp <%s> server <%s> share <%s> clidev <%s>\n", state->mask, srv->master, srv->workgroup, srv->server_name, srv->share_name, cli->dev));
+	if (*srv->workgroup == 0 && *srv->server_name == 0) 
+	{
+		smbwrp_special_add(".", state);
+		smbwrp_special_add("..", state);
+		cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
+				   smbwrp_share_add, state);
+	} else 
+	if (*srv->server_name == 0) 
+	{
+		smbwrp_special_add(".", state);
+		smbwrp_special_add("..", state);
+
+		cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
+				   smbwrp_share_add, state);
+	} else 
+	if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0)) 
+	{
+		smbwrp_special_add(".", state);
+		smbwrp_special_add("..", state);
+		if (cli_RNetShareEnum(cli, smbwrp_share_add, state) < 0) 
+		{
+			return os2cli_errno(cli);
+		}
+	} else 
+	if (strncmp(cli->dev,"LPT",3) == 0) 
+	{
+		smbwrp_special_add(".", state);
+		smbwrp_special_add("..", state);
+		if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0) 
+		{
+			return os2cli_errno(cli);
+		}
+	} 
+	else 
+	{
+#if 0
+		if (strcmp(path,"\\") == 0) {
+			smbwrp_special_add(".", state);
+			smbwrp_special_add("..", state);
+		}
+#endif
+#if 0
+		if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR, 
+			     smbwrp_dir_add_old, state) < 0) 
+#else
+		if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR, 
+			     smbwrp_dir_add, state) < 0) 
+#endif
+		{
+			return os2cli_errno(cli);
+		}
+	}
+
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for chdir()
+*******************************************************/
+int _System smbwrp_chdir(cli_state * cli, char *fname)
+{
+	unsigned short mode = aDIR;
+	smbwrp_fileinfo finfo = {0};
+	if (!cli || !fname) 
+	{
+		return EINVAL;
+	}
+
+	strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
+	if (!smbwrp_getattr(cli, &finfo)) 
+	{
+		return os2cli_errno(cli);
+	}
+
+	if (!(finfo.attr & aDIR)) {
+		return ENOTDIR;
+	}
+
+	return 0;
+}
+
+
+/***************************************************** 
+a wrapper for mkdir()
+*******************************************************/
+int _System smbwrp_mkdir(cli_state * cli, char *fname)
+{
+	if (!cli || !fname) 
+	{
+		return EINVAL;
+	}
+
+	if (!cli_mkdir(cli, fname)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+/***************************************************** 
+a wrapper for rmdir()
+*******************************************************/
+int _System smbwrp_rmdir(cli_state * cli, char *fname)
+{
+	if (!cli || !fname) 
+	{
+		return EINVAL;
+	}
+
+	if (!cli_rmdir(cli, fname)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+/***************************************************** 
+set EA for a path
+*******************************************************/
+int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
+{
+	if (!cli || !fname || !name) 
+	{
+		return EINVAL;
+	}
+	if (!cli_set_ea_path(cli, fname, name, value, size)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+/***************************************************** 
+set EA for a file
+*******************************************************/
+int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
+{
+	if (!cli || !file || !name) 
+	{
+		return EINVAL;
+	}
+	if (!cli_set_ea_fnum(cli, file->fd, name, value, size)) 
+	{
+		return os2cli_errno(cli);
+	}
+	return 0;
+}
+
+
+#pragma pack(1)
+typedef struct _FEA         /* fea */
+{
+         unsigned char fEA;           /* flags                              */
+         unsigned char cbName;        /* name length not including NULL */
+         unsigned short cbValue;     /* value length */
+} FEA;
+
+typedef struct _FEALIST     /* feal */
+{
+	unsigned long cbList;       /* total bytes of structure including full list */
+	FEA list[1];        /* variable length FEA structures */
+} FEALIST;
+#pragma pack()
+
+static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
+{
+	int fnum, i;
+	int gotsize = sizeof(unsigned long);
+	size_t num_eas;
+	struct ea_struct *ea_list = NULL;
+	TALLOC_CTX *mem_ctx;
+	FEA * p;
+	FEALIST * pfealist;
+	char * q;
+
+	mem_ctx = talloc_init("%d: ealist", _gettid());
+	pfealist = (FEALIST *)buffer;
+	pfealist->cbList = 0;
+
+	if (file)
+	{
+		if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list)) 
+		{
+			DEBUG(4,("ea_get_fnum list failed - %s\n", cli_errstr(cli)));
+			talloc_destroy(mem_ctx);
+			return os2cli_errno(cli);
+		}
+	}
+	else
+	{
+		if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) 
+		{
+			DEBUG(4,("ea_get_file list failed - %s\n", cli_errstr(cli)));
+			talloc_destroy(mem_ctx);
+			return os2cli_errno(cli);
+		}
+	}
+
+	DEBUG(4,("num_eas = %d\n", num_eas));
+
+	// we will count that os/2 max EA size for file is 64kb
+	p = pfealist->list;
+	for (i = 0; i < num_eas; i++) 
+	{
+		int namelen = strlen(ea_list[i].name);
+		DEBUG(4, ("%d Got EA <%s> with namelen %d, size %d. Gross %d. Buf %d\n", i, ea_list[i].name, namelen, ea_list[i].value.length, gotsize, size));
+		if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
+		{
+			DEBUG(4, ("Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length));
+			continue;
+		}
+		gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
+		if (size >= gotsize)
+		{
+			p->fEA = 0;
+			p->cbName = namelen;
+			p->cbValue = ea_list[i].value.length;
+			q = (char *)(p + 1);
+			strncpy(q, ea_list[i].name, namelen + 1);
+			q += namelen + 1;
+			memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
+			p = (FEA *)(q + ea_list[i].value.length);
+		}
+	}
+	pfealist->cbList = gotsize;
+	DEBUG(4,("ret size = %d\n", gotsize));
+
+	talloc_destroy(mem_ctx);
+	return 0;
+}
+
+/***************************************************** 
+lists EA of a path
+*******************************************************/
+int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
+{
+	if (!cli || !fname || !buffer)
+	{
+		return EINVAL;
+	}
+
+	DEBUG(4,("EALIst for <%s>\n", fname));
+	return unilistea(cli, fname, NULL, buffer, size);
+}
+
+/***************************************************** 
+lists EA of a file
+*******************************************************/
+int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
+{
+	if (!cli || !file || !buffer)
+	{
+		return EINVAL;
+	}
+
+	DEBUG(4,("FEALIst for <%s>/%d\n", file->fname, file->fd));
+	return unilistea(cli, NULL, file, buffer, size);
+}
+
+/****************************************************************************
+Check the space on a device.
+****************************************************************************/
+int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
+{
+	int total, bsize, avail;
+
+	if (!cli || !pfsa)
+	{
+		return EINVAL;
+	}
+
+	if (!cli_dskattr(cli, &bsize, &total, &avail)) 
+	{
+		DEBUG(4,("Error in dskattr: %s\n",cli_errstr(cli)));
+		return os2cli_errno(cli);
+	}
+
+	DEBUG(4,("\n\t\t%d blocks of size %d. %d blocks available\n",
+		 total, bsize, avail));
+
+	// YD currently Samba return it in MB!
+	pfsa->cSectorUnit = 1;
+	if (bsize > 65536) 
+	{
+		pfsa->cUnit = total*1024;
+		pfsa->cUnitAvail = avail*1024;
+		pfsa->cbSector = bsize/1024;
+	} 
+	else 
+	{
+		pfsa->cUnit = total;
+		pfsa->cUnitAvail = avail;
+		pfsa->cbSector = bsize;
+	}
+
+	return 0;
+}
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.h
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.h	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.h	(revision 5)
@@ -0,0 +1,146 @@
+#ifndef _SMBWRP_H
+#define _SMBWRP_H
+
+#if !defined (O_RDONLY)
+#define O_ACCMODE       0x03    /* mask */
+#define O_RDONLY        0x00
+#define O_WRONLY        0x01
+#define O_RDWR          0x02
+#define O_NONBLOCK      0x04
+#define O_APPEND        0x08
+#define O_TEXT          0x10
+
+#define O_BINARY        0x0100
+#define O_CREAT         0x0200
+#define O_TRUNC         0x0400
+#define O_EXCL          0x0800
+#define O_SYNC          0x2000
+#define O_NOCTTY        0x4000
+#define O_SIZE          0x8000
+#endif
+
+#if !defined (DENY_NONE)
+/* deny modes */
+#define DENY_DOS 0
+#define DENY_ALL 1
+#define DENY_WRITE 2
+#define DENY_READ 3
+#define DENY_NONE 4
+#define DENY_FCB 7
+#endif
+
+
+/* these define the attribute byte as seen by DOS */
+#ifndef aRONLY
+#define aRONLY (1L<<0)		/* 0x01 */
+#define aHIDDEN (1L<<1)		/* 0x02 */
+#define aSYSTEM (1L<<2)		/* 0x04 */
+#define aVOLID (1L<<3)		/* 0x08 */
+#define aDIR (1L<<4)		/* 0x10 */
+#define aARCH (1L<<5)		/* 0x20 */
+#endif
+
+#pragma pack(1)
+
+#ifdef CLI_BUFFER_SIZE
+typedef	struct cli_state cli_state;
+#else
+typedef	unsigned long cli_state;
+#endif
+
+#define CAP_NOPATHINFO2 0x01000000
+
+typedef struct smbwrp_server 
+{
+	char server_name[256];
+	char share_name[256];
+	char workgroup[256];
+	char username[256];
+	char password[256];
+	char master[256];
+	int ifmastergroup;
+	int no_pathinfo2;
+} smbwrp_server;
+
+typedef struct smbwrp_file 
+{
+	int fd;
+	unsigned long long offset;
+	int openmode;
+	int openattr;
+	int denymode;
+	unsigned long mtime;
+	char fullname[261];
+	char fname[261];
+} smbwrp_file;
+
+typedef struct smbwrp_fileinfo
+{
+	unsigned long long size;
+	unsigned long attr;
+	unsigned long ctime;
+	unsigned long mtime;
+	unsigned long atime;
+	int easize;
+	char fname[261];
+} smbwrp_fileinfo;
+
+typedef struct smbwrp_fileseek
+{
+	int whence;
+	long offset;
+	unsigned long result;
+} smbwrp_fileseek;
+
+
+typedef struct filelist_state
+{
+	unsigned long pipe;
+	char * data;
+	int datalen;
+	int bufferlen;
+	void (_System * add_dir_entry)(void * st);
+	char mask[261];
+	smbwrp_fileinfo finfo;
+} filelist_state;
+
+#ifndef INCL_DOS
+typedef struct _FSALLOCATE      /* fsalloc */
+{
+	unsigned long  idFileSystem;
+	unsigned long  cSectorUnit;
+	unsigned long  cUnit;
+	unsigned long  cUnitAvail;
+	unsigned short cbSector;
+} FSALLOCATE;
+#endif
+
+
+#pragma pack()
+
+int _System smbwrp_getclisize(void);
+int _System smbwrp_init(void);
+int _System smbwrp_connect(smbwrp_server * srv, cli_state * c);
+void _System smbwrp_disconnect(cli_state * cli);
+int _System smbwrp_open(cli_state * cli, smbwrp_file * file);
+int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result);
+int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result);
+int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset);
+int _System smbwrp_close(cli_state * cli, smbwrp_file * file);
+int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo);
+int _System smbwrp_getattr(cli_state * cli, smbwrp_fileinfo *finfo);
+int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo);
+int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state);
+int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname);
+int _System smbwrp_chdir(cli_state * cli, char *fname);
+int _System smbwrp_mkdir(cli_state * cli, char *fname);
+int _System smbwrp_rmdir(cli_state * cli, char *fname);
+int _System smbwrp_unlink(cli_state * cli, const char *fname);
+int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize);
+int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size);
+int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size);
+int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size);
+int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size);
+int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa);
+
+#endif /* _SMBWRP_H */
Index: /trunk/samba-3.0.25pre1/source/ndpsmb/test.c
===================================================================
--- /trunk/samba-3.0.25pre1/source/ndpsmb/test.c	(revision 5)
+++ /trunk/samba-3.0.25pre1/source/ndpsmb/test.c	(revision 5)
@@ -0,0 +1,62 @@
+#include "includes.h"
+
+int  main(void)
+{
+	fstring server, share, user, password;
+	pstring workgroup;
+	pstring path;
+	struct in_addr rem_ip;
+        struct in_addr server_ip;
+
+	DEBUGLEVEL = 10;
+	setup_logging("test", True);
+	init_globals();
+
+	load_interfaces();
+
+	if (!init_names())
+	{
+		return 1;
+	}
+
+//	strncpy(workgroup, "I-TEL", sizeof(workgroup) - 1);
+	strncpy(workgroup, "xxx", sizeof(workgroup) - 1);
+//	*workgroup = 0;
+	*server = 0;
+	*share = 0;
+	*password = 0;
+	strncpy(user, "guest", sizeof(user) - 1);
+	
+printf("1\n");
+	if (!find_master_ip(workgroup, &server_ip)) {
+	    struct user_auth_info u_info;
+	    struct cli_state *cli;
+printf("2\n");
+		    DEBUG(4, ("Unable to find master browser for workgroup %s\n", 
+		      workgroup));
+		    /* find the name of the server ... */
+	    pstrcpy(u_info.username, user);
+	    pstrcpy(u_info.password, password);
+
+printf("3\n");
+	    if (!(cli = get_ipc_connect_master_ip_bcast(workgroup, &u_info))) {
+		DEBUG(4, ("Unable to find master browser by "
+			  "broadcast\n"));
+		errno = ENOENT;
+		return 1;
+	    }
+printf("4\n");
+
+	    fstrcpy(server, cli->desthost);
+printf("4 <%s>\n", server);
+	    cli_shutdown(cli);
+	} else {
+printf("5\n");
+	    if (!name_status_find("*", 0, 0, server_ip, server)) {
+		errno = ENOENT;
+		return 1;
+	    }
+printf("6 <%s>\n", server);
+	}	
+	return 0;
+}
