skyrope-mit-merge-hell-20040226
authorJeffrey Altman <jaltman@mit.edu>
Thu, 26 Feb 2004 19:22:35 +0000 (19:22 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 26 Feb 2004 19:22:35 +0000 (19:22 +0000)
From Skyrope:

The Skyrope work attempted to improve on the end user experience of using
OpenAFS in the following ways:

   * Obtain tokens using renewable Kerberos 5 tickets in order to
     reduce the need for end users to renew expired tokens
   * Monitor the list of IP Addresses in order to detect changes
     in the network configuration which might affect the reachability
     of cells or the state of the AFS Client Service.  When cells
     are newly reachable, obtain tokens for the cells.  If the AFS
     Client Service is not running, start it.  If tokens are expiring
     attempt to renew them.
   * Use KDC probes to detect the accessibility of realms/cells.  If
     the KDC is not reachable, do not prompt the end user for a
     username and password.  (fs probe is not implemented on windows)
   * Automatically obtain tokens using the Windows Logon Session
     Kerberos credentials (if available)
   * Allow tokens for multiple cells to be obtained by using the
     same Kerberos 5 tickets.  (no UI yet implemented)
   * Perform drive mapping persistance by tracking it within the
     afsdsbmt.ini file instead of relying on the Windows Shell
     to persist the state.
   * Add new afscreds.exe command line options and change the
     default set used when creating the "AFS Credentials" shortcut
     in the Start Menu->Programs->Startup folder.

From MIT:

   * Auto-detection of loopback adapters.  Use "AFS" as the netbios
     name when a loopback adapter is installed.

   * Support for responding to power management events.  Used to
     flush the cache when the machine is about to suspend, hibernate,
     or shutdown

   * Documentation of Registry entries

   * Support for Extended SMB Requests

   * Beginning of support for true Event Log reporting from a
     message database

   * Hidden Dot File support (configured via the HideDotFiles
     registry option)

   * Configurable Max number of Multiplexed Sessions (MaxMpxRequests
     registry option)

   * Configurable Max MTU size (RxMaxMTU registry option)

   * Configurable Jumbogram support (RxNoJumbo registry option)

   * Configurable Max number of Virtual Connections per Server
     (MaxVCPerServer registry option)

   * Win32 DNS API support

   * Addition of SMB_ATTR_xxxx defines for use instead of hex numbers

   * A variety of heap access and resource deallocation errors corrected
     in the SMB code

   * Support for recursive directory creation

   * Modifications to the en_US version of the client configuration
     dialog (need to port to other languages)

Notes on the current check-in:

   * The KfW code will always be used when installed on the machine.
     This code only supports Krb5 and will not work with Krb4 only
     realms.  A registry flag indicating whether or not KfW should be
     used if found needs to be added.

   * afscreds.exe needs to have a registry entry created to control
     the parameter list it should be started with.  There should be
     a dialog to control this in the installer and within afscreds.exe

   * The MIT method of auto-assigning the mount-root and the netbios
     name is in conflict with the morgan stanley submissions in some
     parts of the code.  If you are using the loopback adapter with
     this code both the "NetbiosName" = "AFS" and "Mountroot" = "/afs"
     registry options must be specified.  This will be fixed in coming
     days.

135 files changed:
doc/txt/winnotes/registry.txt [new file with mode: 0644]
src/NTMakefile
src/README-NT
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd_eventlog.c [new file with mode: 0644]
src/WINNT/afsd/afsd_eventlog.h [new file with mode: 0644]
src/WINNT/afsd/afsd_eventmessages.mc [new file with mode: 0644]
src/WINNT/afsd/afsd_eventmessages.rc [new file with mode: 0644]
src/WINNT/afsd/afsd_flushvol.c [new file with mode: 0644]
src/WINNT/afsd/afsd_flushvol.h [new file with mode: 0644]
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/fs_utils.c
src/WINNT/afsd/fs_utils.h
src/WINNT/afsd/lanahelper.cpp [new file with mode: 0644]
src/WINNT/afsd/lanahelper.h [new file with mode: 0644]
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afssvrcfg/NTMakefile
src/WINNT/afssvrcpa/NTMakefile
src/WINNT/client_config/NTMakefile
src/WINNT/client_config/RegistrySupport.cpp [new file with mode: 0644]
src/WINNT/client_config/config.cpp
src/WINNT/client_config/dlg_automap.cpp
src/WINNT/client_config/dlg_binding.cpp [new file with mode: 0644]
src/WINNT/client_config/dlg_misc.cpp
src/WINNT/client_config/drivemap.cpp
src/WINNT/client_config/drivemap.h
src/WINNT/client_config/getlana.cpp [new file with mode: 0644]
src/WINNT/client_config/getlana.h [new file with mode: 0644]
src/WINNT/client_config/lang/en_US/afs_config.rc
src/WINNT/client_config/lang/zh_CN/afs_config.rc
src/WINNT/client_config/resource.h
src/WINNT/client_config/tab_advanced.cpp
src/WINNT/client_config/tab_drives.cpp
src/WINNT/client_creds/Makefile
src/WINNT/client_creds/NTMakefile
src/WINNT/client_creds/advtab.cpp
src/WINNT/client_creds/afscreds.h
src/WINNT/client_creds/afskfw-int.h [new file with mode: 0644]
src/WINNT/client_creds/afskfw.c [new file with mode: 0644]
src/WINNT/client_creds/afskfw.h [new file with mode: 0644]
src/WINNT/client_creds/creds.cpp
src/WINNT/client_creds/main.cpp
src/WINNT/client_creds/mounttab.cpp
src/WINNT/client_creds/shortcut.cpp
src/WINNT/client_creds/window.cpp
src/WINNT/client_exp/gui2fs.cpp
src/WINNT/client_exp/partition_info_dlg.cpp
src/WINNT/client_exp/shell_ext.cpp
src/WINNT/client_exp/shell_ext.h
src/WINNT/client_osi/NTMakefile
src/WINNT/client_osi/largeint.h [new file with mode: 0644]
src/WINNT/client_osi/libosi.def
src/WINNT/client_osi/osi.h
src/WINNT/client_osi/osilog.c
src/WINNT/client_osi/osilog.h
src/WINNT/client_osi/osistatl.h
src/WINNT/doc/help/en_US/afs-cc.CNT
src/WINNT/doc/help/en_US/afs-light.CNT
src/WINNT/doc/help/en_US/afs-nt.CNT
src/WINNT/doc/help/en_US/taafscfg.cnt
src/WINNT/doc/help/en_US/taafssvrmgr.cnt
src/WINNT/doc/help/en_US/taafsusrmgr.cnt
src/WINNT/kfw/inc/kclient/kclient.h [new file with mode: 0644]
src/WINNT/kfw/inc/kclient/kcmacerr.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/com_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/conf-pc.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/conf.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/des.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/kadm_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/krb.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/krberr.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/mit_copy.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb4/osconf.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/KerberosIV/des.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/KerberosIV/kadm_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/KerberosIV/krb.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/KerberosIV/krb_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/KerberosIV/mit-copyright.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/com_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/gssapi/gssapi.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/gssapi/gssapi_generic.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/gssapi/gssapi_krb5.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/krb5.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/profile.h [new file with mode: 0644]
src/WINNT/kfw/inc/krb5/win-mac.h [new file with mode: 0644]
src/WINNT/kfw/inc/krbcc/cacheapi.h [new file with mode: 0644]
src/WINNT/kfw/inc/leash/leasherr.h [new file with mode: 0644]
src/WINNT/kfw/inc/leash/leashinfo.h [new file with mode: 0644]
src/WINNT/kfw/inc/leash/leashwin.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-afs.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-afs36.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-com_err.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-krb.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-krb5.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-krb524.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-leash.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-lsa.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-profile.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs-wshelper.h [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs.c [new file with mode: 0644]
src/WINNT/kfw/inc/loadfuncs/loadfuncs.h [new file with mode: 0644]
src/WINNT/kfw/inc/wshelper/arpa/nameser.h [new file with mode: 0644]
src/WINNT/kfw/inc/wshelper/hesiod.h [new file with mode: 0644]
src/WINNT/kfw/inc/wshelper/mitwhich.h [new file with mode: 0644]
src/WINNT/kfw/inc/wshelper/resolv.h [new file with mode: 0644]
src/WINNT/kfw/inc/wshelper/wshelper.h [new file with mode: 0644]
src/WINNT/kfw/lib/i386/comerr32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/delaydlls.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/getopt.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/gssapi32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/kclnt32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/krb524.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/krb5_32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/krbcc32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/krbv4w32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/leashw32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/loadfuncs.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/wshelp32.lib [new file with mode: 0644]
src/WINNT/kfw/lib/i386/xpprof32.lib [new file with mode: 0644]
src/config/NTMakefile.i386_nt40
src/config/param.sun4_413.h
src/libafsauthent/NTMakefile
src/libafsrpc/afsrpc.def
src/rx/rx_clock_nt.c
src/rx/rx_user.c
src/sys/pioctl_nt.c

diff --git a/doc/txt/winnotes/registry.txt b/doc/txt/winnotes/registry.txt
new file mode 100644 (file)
index 0000000..da79e58
--- /dev/null
@@ -0,0 +1,241 @@
+
+Registry keys used in the Windows AFS Client
+--------------------------------------------
+
+This file describes the registry keys used in the Windows AFS clients.
+
+1. Service parameters
+---------------------
+
+The service parameters primarily affect the behavior of the AFS client
+service (afsd_service.exe).
+
+Regkey:
+[HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters]
+
+Value   : LANadapter
+Type    : DWORD
+Default : -1
+Variable: LANadapter
+
+  LAN adapter number to use.  This is the lana number of the LAN
+  adapter that the SMB server should bind to.  If unspecified or set
+  to -1, a LAN adapter with named 'AFS' or a loopback adapter will be
+  selected.  If neither are present, then all available adapters will
+  be bound to.  When binding to a non-loopback adapter, the NetBIOS
+  name '%hostname%-AFS' will be used (where %hostname% is the NetBIOS
+  name of the host truncated to 11 characters). Otherwise, the NetBIOS
+  name will be 'AFS'.
+
+Value   : CacheSize
+Type    : QWORD
+Default : 20480 (CM_CONFIGDEFAULT_CACHESIZE)
+Variable: cm_initParams.cacheSize
+
+  Size of the AFS cache.
+
+Value   : ChunkSize
+Type    : DWORD
+Default : 15 (CM_CONFIGDEFAULT_CHUNKSIZE)
+Variable: cm_logChunkSize (cm_chunkSize = 1 << cm_logChunkSize)
+
+  Size of chunk for reading and writing. Actual chunk size is 2^cm_logChunkSize.
+
+Value   : Daemons
+Type   : DWORD
+Default : 2 (CM_CONFIGDEFAULT_DAEMONS)
+Variable: numBkgD
+
+  Number of background daemons (number of threads of
+  cm_BkgDaemon). (see cm_BkgDaemon in cm_daemon.c)
+
+Value  : ServerThreads
+Type   : DWORD
+Default        : 4 (CM_CONFIGDEFAULT_SVTHREADS)
+Variable: numSvThreads
+
+  Number of SMB server threads (number of threads of smb_Server). (see
+  smb_Server in smb.c).
+
+Value  : Stats
+Type   : QWORD
+Default : 1000 (CM_CONFIGDEFAULT_STATS)
+Variable: cm_initParams.nStatCaches
+
+  Cache configuration.
+
+Value  : LogoffTokenTransfer
+Type   : DWORD {1,0}
+Default : 1
+Variable: smb_LogoffTokenTransfer
+
+  If enabled (set to 1), activates functionality where the user's
+  tokens are kept intact until smb_LogofTokenTransferTimeout seconds
+  elapse after user logs off.  If roaming profiles are used and the
+  roaming profile takes a long time to be written back, this ensures
+  that the tokens remain valid until the profile save is complete.
+
+Value  : LogoffTokenTransferTimeout
+Type   : QWORD
+Default : 10
+Variable: smb_LogoffTokenTransferTimeout
+
+  See LogoffTokenTransfer above.
+
+Value  : RootVolume
+Type   : REG_SZ
+Default : "root.afs"
+Variable: cm_rootVolumeName
+
+  Root volume name.
+
+Value  : Mountroot
+Type   : REG_SZ
+Default : "/afs"
+Variable: cm_mountRoot
+
+  Name of root mount point.  In symlinks, if a path starts with
+  cm_mountRoot, it is assumed that the path is absolute (as opposed to
+  relative) and is adjusted accordingly. Eg: if a path is specified as
+  /afs/athena.mit.edu/foo/bar/baz and cm_mountRoot is "/afs", then the
+  path is interpreted as \\afs\all\athena.mit.edu\foo\bar\baz.  If a
+  path does not start with with cm_mountRoot, the path is assumed to
+  be relative and suffixed to the reference directory (i.e. directory
+  where the symlink exists)
+Value  : CachePath
+Type   : REG_SZ
+Default : "\AFSCache"
+Variable: cm_CachePath
+
+  Location of on-disk cache file.
+
+Value  : TrapOnPanic
+Type   : DWORD {1,0}
+Default : 0
+Variable: traceOnPanic
+
+  Issues a breakpoint in the event of a panic. (breakpoint: _asm int 3).
+
+Value  : IsGateway
+Type   : DWORD {1,0}
+Default : 0
+Variable: isGateway
+
+  Select whether or not this AFS client should act as a gateway.  If
+  set and the NetBIOS name hostname-AFS is bound to a physical NIC,
+  other machines in the subnet can access AFS via SMB connections to
+  hostname-AFS .
+
+Value  : ReportSessionStartups
+Type   : DWORD {1,0}
+Default : 0
+Variable: reportSessionStartups
+
+  If enabled, all SMB sessions created are recorded in the Application
+  event log.
+
+Value  : TraceBufferSize
+Type   : QWORD
+Default : 5000 (CM_CONFIGDEFAULT_TRACEBUFSIZE)
+Variable: traceBufSize
+
+  Number of entries to keep in trace log.
+
+Value  : SysName
+Type   : REG_SZ
+Default : "i386_nt40"
+Variable: cm_sysName
+
+  Self explanatory.
+
+Value  : SecurityLevel
+Type   : DWORD {1,0}
+Default : 0
+Variable: cryptall
+
+  Enables encryption on RX calls.
+
+Value  : UseDNS
+Type   : DWORD {1,0}
+Default : 1
+Variable: cm_dnsEnabled
+
+  Enables resolving volservers using AFSDB DNS queries. (see
+  afsdb-freelance-notes)
+
+Value  : FreelanceClient
+Type   : DWORD {1,0}
+Default : 0
+Variable: cm_freelanceEnabled
+
+  Enables freelance client. (see afsdb-freelance-notes)
+
+Value  : HideDotFiles
+Type   : DWORD {1,0}
+Default : 1
+Variable: smb_hideDotFiles
+
+  Enables marking dotfiles with the hidden attribute.  Dot files are
+  files whose name starts with a period (excluding "." and "..").
+
+Value  : MaxMpxRequests
+Type   : DWORD
+Default : 50
+Variable: smb_maxMpxRequests
+
+  Maximum number of multiplexed SMB requests that can be made.
+
+Value  : MaxVCPerServer
+Type   : DWORD
+Default : 100
+Variable: smb_maxVCPerServer
+
+  Maximum number of SMB virtual circuits.
+
+Value  : Cell
+Type   : REG_SZ
+Default : <none>
+Variable: rootCellName
+
+  Name of root cell (the cell from which root.afs should be mounted in
+  \\afs\all).
+
+Value  : RxNoJumbo
+Type   : DWORD {0,1}
+Default : 0
+Variable: rx_nojumbo
+
+  If enabled, does not send or indicate that we are able to send or
+  receive RX jumbograms.
+
+Value  : RxMaxMTU
+Type   : DWORD
+Default : -1
+Variable: rx_mtu
+
+  If set to anything other than -1, uses that value as the maximum MTU
+  supported by the RX interface.
+
+2. Network provider parameters
+------------------------------
+Affects the network provider (aklogon.dll).
+
+Regkey:
+[HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters]
+
+Value  : FailLoginsSilently
+Type   : DWORD
+Default : 0
+
+Do not display message boxes if the login fails.
+
+Regkey:
+[HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider]
+
+Value   : NoWarnings
+Type   : DWORD
+Default : 0
+
+Disables visible warnings during logon.
+
index 05af7ee..f224da7 100644 (file)
@@ -537,7 +537,18 @@ client_creds: client_exp
        $(NTMAKE)
        $(CD) ..\..\..
 
-finale: client_creds
+extra: client_creds
+!      IF EXIST($(SRC)\WINNT\extra) && EXIST($(SRC)\WINNT\extra\NTMakefile)
+     echo ***** $@
+    $(DOCD) $(SRC)\WINNT\$@
+       $(CD) $(SRC)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+!      ELSE
+     echo ***** Skipping $@ ***** Not found.
+!      ENDIF
+                
+finale: extra
      echo ***** $@
        $(DOCD) $(SRC)\$@
        $(CD) $(SRC)\$@
@@ -549,20 +560,6 @@ install: finale
 
 # InstallShield dependencies
 
-InstallShield5:
-       echo ***** afs_setup_utils
-       $(DOCD) $(SRC)\WINNT\afs_setup_utils
-       $(CD) $(SRC)\WINNT\afs_setup_utils
-       $(NTMAKE)
-       $(CD) ..\..\..
-
-       $(DOCD) $(SRC)\WINNT\install\$@
-       $(CD) $(SRC)\WINNT\install\$@
-       $(NTMAKE)
-       $(CD) ..\..\..\..
-
-media: InstallShield5 NSIS
-
 # Clean target for obj tree
 clean:
        nmake /nologo /f ntmakefile "NTMAKE = nmake /nologo /f ntmakefile clean" "NTMAKE_HEADERS = nmake /nologo /f ntmakefile clean" "NTMAKE_OBJS = nmake /nologo /f ntmakefile clean" install
@@ -586,12 +583,35 @@ mkdir:
 
 NSIS:
    echo ***** Making NSIS Installer
-   $(DOCD) $(SRC)\WINNT\install\NSIS
-   $(CD) $(SRC)\WINNT\install\NSIS
+   $(DOCD) $(SRC)\WINNT\install\$@
+   $(CD) $(SRC)\WINNT\install\$@
    $(NTMAKE)
    $(CD) ..\..\..\..
 
+#msi:
+#   echo ***** Making MSI Installer
+#   $(DOCD) $(SRC)\WINNT\install\$@
+#   $(CD) $(SRC)\WINNT\install\$@
+#   $(NTMAKE)
+#   $(CD) ..\..\..\..
+
+InstallShield5:
+       echo ***** afs_setup_utils
+       $(DOCD) $(SRC)\WINNT\afs_setup_utils
+       $(CD) $(SRC)\WINNT\afs_setup_utils
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+       $(DOCD) $(SRC)\WINNT\install\$@
+       $(CD) $(SRC)\WINNT\install\$@
+       $(NTMAKE)
+       $(CD) ..\..\..\..
+
+media: install InstallShield5 NSIS
+
 install-nsis: install NSIS
 
+install-msi: install msi
+
 install-is5: install InstallShield5
 
index 445a6e8..c802d27 100644 (file)
-This software has been released under the terms of the IBM Public\r
-License.  For details, see the LICENSE file in the top-level source\r
-directory or on-line at http://www.openafs.org/dl/license10.html\r
-\r
-The document now provides a step by step procedure that takes the user \r
-from a basic Windows NT/2000 workstation to an OpenAFS development \r
-environment.   Details are provided so that a 'beginning' windows \r
-developer can build an OpenAFS installable package for Windows NT/2000.  \r
-\r
-***********   Windows NT/2000 Build Process ****************\r
-\r
-Building OpenAFS for Windows requires configuring a Windows\r
-development system by installing compilation tools and header files.\r
-Open AFS Software development can be done on Windows NT or 2000.  The\r
-target system, where OpenAFS will be installed, should be either\r
-Windows NT or Windows 2000.  The building process is controlled by a\r
-nmake file that generates the necessary binaries and binds them into an\r
-install package.\r
-\r
-The following steps describe how to configure Windows 2000/NT:\r
-\r
-   A. Obtain a copy of the OpenAFS Source Tree\r
-   B. Install Compiler and Development tools.\r
-   C. Set up drive mappings.\r
-   D. Install SDK header files\r
-   E. Configure Environment variables\r
-   F. Set program version Level\r
-   G. Build Win2000 binaries\r
-   H. Install InstallShield 5.x\r
-   I. Build Win2000 InstallShield Package\r
-   J. Build Win2000 InstallShield Package for the Web\r
-   K. Final Results\r
-   L. Creating a Debug Environment\r
-   M. Optional Items\r
-   N. Required patches for 1.2.2a and earlier releases\r
-       \r
-The Software development tools with InstallShield require 900 MB\r
-storage.\r
-\r
-The Software development tools (without InstallShield) require 660 MB\r
-storage.\r
-\r
-The OpenAFS Source directory requires about 200 MB storage. The Source\r
-directory size includes additional space for files that will be\r
-generated during the build process.\r
-\r
-The following CDs are used in this example:\r
-       Microsoft SDK and Tools Jan 2001\r
-       Microsoft Visual Studio Version 6.0\r
-       InstallShield 5.5\r
-\r
-Different versions of above CDs can be used; however, building an\r
-install package for Windows NT/2000 requires InstallShield\r
-version 5.0 to 5.5 (version 6.0 or better will not work).  \r
-\r
-You can build all the necessary binaries without the InstallShield\r
-software. InstallShield is only needed to build an install package.\r
-\r
-STEP A. Obtain a copy of the Open AFS Source Tree.\r
-\r
-Transfer OpenAFS source tree onto your hardrive.  The source can be\r
-downloaded from the OpenAFS web site:\r
-       http://www.OpenAFS.org/release/snapindex.html.\r
-\r
-For this example, download source for version 1.2.2a using the\r
-following URL:\r
-http://www.openafs.org/dl/openafs/1.2.2a/openafs-1.2.2a-src.tar\r
-\r
-HINT: DailySnapShots are pre-release source trees and much more\r
-likely to have compilation errors. If this is your first attempt, do\r
-your build based on a release version of the source, e.g. 1.2.2.a. Once\r
-you have completed a build process successfully, you can experiment with\r
-other source trees.\r
-\r
-You will need an unzip utility that can expand compressed tar files.\r
-For example "Pkzip for Windows" from Pkware will uncompress tar files.\r
-(http://www.pkware.com/)\r
-\r
-Expand the downloaded tar file (openafs-1.2.2a-src.tar) into target\r
-directory (c:\OpenAFS), the unzip routine will expand the source into a\r
-subdirectory tree:\r
-               c:\OpenAFS\OpenAFS-1.2.2a\src\r
-\r
-Copy files NTMAKEFILE from 'src' to the AFS base directory:\r
-\r
-From a DOS command prompt window, enter the following copy commands:\r
-\r
-copy c:\OpenAFS\OpenAFS-1.2.2a\src\NTMAKEFILE c:\OpenAFS\OpenAFS-1.2.2a\.\r
-\r
-The AFS base directory should look something like the following:\r
-\r
-c:\OpenAFS\OpenAFS-1.2.2a\\r
-  NTMakefile\r
-  src\r
-         \r
-STEP B. Install compiler and development tools.\r
-\r
-Install a copy of Microsoft Visual C++ 5.0 or 6.0. The "Typical" install\r
-setting is sufficient.\r
-\r
-(1) You can reduce the installation size by selecting "Custom" install\r
-and remove all but the following Options:\r
-\r
-       Microsoft Visual C++\r
-       Data Access\r
-\r
-(2) When asked, Select to Register Environment Variables.\r
-\r
-(3) After rebooting you have to choice to install additional software\r
-packages. It is not necessary to install these packages.\r
-\r
-STEP C. Map development drive letters.\r
-\r
-The following documentation will assume you are mapping the Y: drive to\r
-the OpenAFS source directory and you are mapping X: drive to your\r
-development tools directory. Other configurations will work, including\r
-not mapping any drives, as long as the path assignments are consistent\r
-and you don't exceed the maximum environment variable length.\r
-\r
-Y: drive mapping provides a consistent directory location to build from.\r
-Building OpenAFS will require you to open up a command DOS prompt,\r
-navigate to drive Y: and execute the nmake file.  The source is based\r
-from Y: drive and the generated files are based from Y:\DEST.  If the OpenAFS \r
-source tree is at a different location, you only need to re-map the\r
-Y: drive.\r
-\r
-X: drive mapping shortens the length of several Environment variables\r
-by mapping it to a directory where Visual Studio is installed. Although\r
-this step is not important when using Windows NT or 2000 as a\r
-development OS, it does reduce the chance of typing errors during\r
-the configuration phase.\r
-\r
-From a DOS command window enter the following commands:\r
-\r
-SUBST  y: c:\OpenAFS\OpenAFS-1.2.2a\r
-SUBST  x: "c:\Program Files\Microsoft Visual Studio\VC98"\r
-\r
-SUBST is persistent across DOS command prompts; that is, if you open up\r
-another DOS command prompt the mapped drives are still defined.\r
-However, if you reboot the mapped drives using SUBST will be lost.  \r
-\r
-If you need to remove Y: drive mapping, execute the following command\r
-from a DOS command prompt window:\r
-\r
-SUBST  y: /d\r
-\r
-STEP D. Install SDK header files.\r
-\r
-Files from Microsoft's Platform SDK for NT or 98 are required to\r
-complete a build on NT/2000.\r
-\r
-The header files that are required are found from a Microsoft SDK are:\r
-\r
-   netspi.h\r
-   npapi.h\r
-\r
-These files come from Microsoft DDKs/SDKs as follows:\r
-\r
-   January 1997 Windows NT Workstation DDK - /ddk/frc/network/inc/npapi.h\r
-   November 2001 Microsoft Platform SDK - install "samples" from "Core SDK"\r
-                              samples/winbase/security/winnt/logonnp/npapi.h\r
-   July 1998 Windows 95 DDK - net/inc/netmpr.h and net/inc/netspi.h\r
-   July 1999 Windows 98 DDK - src/net/inc/netmpr.h and src/net/inc/netspi.h\r
-                            - you need to install "Legacy and Related\r
-                              driver samples"\r
-\r
-To Install Platform SDK from CDROM\r
-       \r
-       Run "setup.exe default.htm" from CDROM:\r
-       Select Microsoft Core SDK\r
-       Select Sample and Source\r
-       Select installation path x:\SDK\r
-\r
-To Install Windows SDK from WEB:\r
-       http://www.microsoft.com/sdk\r
-\r
-STEP E. Configure the OpenAFS build environment.\r
-\r
-The following environment variables should be set:\r
-\r
-SET AFSDEV_LIB=%LIB%\r
-SET AFSROOT=Y:\r
-SET SYS_NAME=i386_nt40\r
-SET _WIN32_IE=0x400\r
-SET MSSDK=X:\Sdk\r
-SET MSTOOLS=X:\Sdk\r
-SET MSVCDIR=X:\r
-SET AFSDEV_BIN=X:\BIN\r
-SET AFSDEV_BUILDTYPE=FREE\r
-SET AFSDEV_INCLUDE=X:\Sdk\samples\winbase\security\winnt\logonNP;X:\Sdk\Include\ATL30;X:\Sdk\Include;%INCLUDE%\r
-\r
-Please do not include unnecessary spaces in AFSDEV_INLCUDE.\r
-\r
-Create a batch file (SETAFS.BAT) to make these settings that can be \r
-executed when you bring up a DOS command prompt window.  Environment \r
-variables are not persistent, if you close the DOS command window \r
-or reboot, the environment variables are lost and they must be \r
-recreated when you open a new DOS command prompt window.\r
-\r
-HINT: SET AFSDEV_BUILDTYPE=CHECKED if you want debug information\r
-included in your binaries.\r
-\r
-HINT: Adding drive mapping commands to the batch file makes it easy to\r
-establish your development environment even if you logoff.  I suggest\r
-adding the following lines to the beginning of the batch file:\r
-\r
-SUBST  y: /d\r
-SUBST  x: /d\r
-SUBST  y: c:\OpenAfs\OpenAFS-1.2.2a\r
-SUBST  x: "c:\Program Files\Microsoft Visual Studio\VC98"\r
-\r
-HINT: Windows 2000/NT provides an alternate way to set environment\r
-variables in System Proprieties.  These can be accessed from the system\r
-control panel, advanced tab, Environment Variables.  These are\r
-persistent and will be reset every time a DOS command prompt window is\r
-opened.\r
-\r
-STEP F. Set version and installation options\r
-\r
-Add a CellServDB file to install area. CellServDB contains the entries\r
-for the various cell names.  You can download a general purpose one\r
-from:\r
-       http://grand.central.org/dl/cellservdb/CellServDB\r
-then copy it to Y:\DEST\Wininstall\Config\CellServDB.GrandCentral\r
-\r
-Note: Create directory Y:\DEST\Wininstall\Config\ if it doesn't exist.\r
-\r
-Edit file Y:\src\config\NTMakefile.i386_nt40\r
-       AFSPRODUCT_VERSION  - Product version\r
-       CELLSERVDB_INSTALL - The default file name for the CellServDB\r
-       included in the install Package.\r
-       CELLNAME_DEFAULT -  The default home cell name.\r
-       CELLSERVDB_WEB  - The default web address to obtain CellServDB\r
-\r
-For example: in the file Y:\src\config\NTMakefile.i386_nt40 you would\r
-see the following:\r
-\r
-   AFSPRODUCT_VERSION=1.2.2a\r
-   CELLNAME_DEFAULT=home.cell.com\r
-   CELLSERVDB_INSTALL=CellServDB.GrandCentral\r
-   CELLSERVDB_WEB=http://grand.central.org/dl/cellservdb/CellServDB\r
-\r
-During the Open AFS installation process the user will be presented\r
-with two choices for the CellServDB: Local copy (CELLSERVDB_INSTALL) and\r
-one that can be downloaded from the web (CELLSERVDB_WEB).\r
-\r
-HINT: The product version number (AFSPRODUCT_VERSION) can be changed to\r
-create a new version number.  For example if you have added source\r
-changes to OpenAFS-1.2.2a and you wanted to create a new version level,\r
-you may want to use the following: AFSPRODUCT_VERSION=1.2.2b\r
-\r
-STEP G. Begin the build\r
-\r
-(1) From Windows 2000 open up a DOS prompt window.\r
-\r
-(2) Clean the work area.\r
-\r
-    nmake /f NTMakefile clean\r
-\r
-(3) Build the complete Windows NT/2000 development environment.\r
-\r
-    nmake /f NTMakefile install\r
-\r
-While the build is running you will see many compile warnings. This\r
-behavior is normal; the build process is successful as long as the build\r
-process doesn't terminate with an error ("nmake.exe return code 0x2")\r
-and it displays 'Build Finished Successfully'.\r
-\r
-STEP H. Install InstallShield (optional).\r
-\r
-In order to build an install package for OpenAFS, InstallShield 5.5\r
-must be installed along with InstallShield East and West\r
-multi-Language packs.\r
-\r
-(1) Install InstallShield (version between 5.0 and  5.5)\r
-\r
-For minimum installation choose "compact".\r
-\r
-(2) Install West Language Pack (5.5)\r
-\r
-(3) Install East Language Pack (5.5)\r
-\r
-NOTE: InstallShield's versions 6 and higher WILL NOT WORK for\r
-Windows NT/2000 build process.\r
-\r
-(4) Add necessary DLL's to work with the InstallShield package.\r
-\r
-Two Microsoft DLL's are missing from the InstallShield package. These\r
-DLL's must be copied to Y:\DEST\WinInstall\Config\:\r
-       SHLWAPI.DLL \r
-       WININET.DLL\r
-\r
-These files are only used during the installation, and they will not \r
-be left on the target machine.  They can be located at \r
-%SystemRoot%\SYSTEM32.\r
-\r
-From a DOS command prompt window enter the following commands:\r
-\r
-copy %systemRoot%\System32\SHLWAPI.DLL y:\dest\wininstall\config\.\r
-copy %systemRoot%\System32\WININET.DLL y:\dest\wininstall\config\.\r
-\r
-(5) Add two Environment variables to the bottom of the batch file,\r
-SETAFS.BAT (see STEP E:).\r
-\r
-SET IS5ROOT="C:\Program Files\InstallShield\InstallShield 5.5 Professional Edition"\r
-SET AFSDEV_INCLUDE=%AFSDEV_INCLUDE%;%IS5ROOT%\Include\r
-\r
-STEP I.  Build Win2000 InstallShield package\r
-\r
-From the DOS command prompt window run:\r
-\r
-       Y:\r
-    nmake /f NTMakefile media\r
-\r
-While the build is running you will see a few compile warnings. This\r
-behavior is normal; the build process is successful as long as the build\r
-process doesn't terminate with an error ("nmake.exe return code 0x2")\r
-and it displays 'Install Script Finished Successfully'.\r
-\r
-STEP J.  Build Win2000 InstallShield package for the Web\r
-\r
-InstallShield's PackageForTheWeb combines the installation files into a\r
-single application file that will expand on execution and lead you\r
-through the OpenAFS installation.   \r
-\r
-Install PackageForTheWeb 3 from InstallShield\r
-\r
-Add Environment variables to the bottom of the batch file, SETAFS.BAT\r
-(see STEP E:).\r
-\r
-SET ISWEB="C:\Program Files\InstallShield\PackageForTheWeb 3"\r
-\r
-From the DOS command prompt window run:\r
-\r
-       Y:\r
-    nmake /f NTMakefile media\r
-\r
-While the build is running you will see a few compile warnings. This\r
-behavior is normal; the build process is successful as long as the build\r
-process doesn't terminate with an error ("nmake.exe return code 0x2") and\r
-it displays 'Install Script Finished Successfully'.\r
-\r
-HINT:  It is only necessary to run "nmake /f NTMakefile media" once, by \r
-combining steps I & J.     \r
-\r
-STEP K. Final Results\r
-\r
-The build process generates its binaries in Y:\DEST. The subdirectory\r
-would look like the following:\r
-\r
-Y:\DEST\r
-       bin\r
-       etc\r
-       include\r
-       lib\r
-       root.client\r
-       root.server\r
-       WinInstall\r
-\r
-Y:\DEST\Bin - contains build utilities.\r
-Y:\DEST\root.client - contains Open AFS binaries\r
-Y:\DEST\root.server - contain Open AFS Server binaries\r
-Y:\DEST\WinInstall\PackageWeb\AFSforWindows.exe - is the Web install\r
-package for Open AFS.\r
-Y:\DEST\WinInstall\ - are the install package files for Open AFS\r
-\r
-Step L. Creating a Debug Environment\r
-\r
-Instructions on building a debugging environment from Visual Studio C++\r
-workspace.  This example give the user a way to step through the source\r
-code for AFSCREDS.EXE.\r
-\r
-These instructions are to be followed after you have set up the\r
-development environment.\r
-\r
-The following steps must be done before you can build a debug\r
-environment:\r
-\r
-1. Set up the development environment as described above\r
-2. set AFS_BUILDTYPE=CHECKED to get debug information.\r
-3. You must use environment variables in System Properties\r
-4. Do a complete build.\r
-\r
-To set the the environment variables in the System Properties:\r
-1. Select the 'System' icon in the control Panel\r
-2. Select the 'Advanced' tab\r
-3. Select the 'Environment Variables' button\r
-4. In the user area set all variables as you did above that\r
-were used in the setafs.bat file.\r
-\r
-To build a new work space to debug afs_creds.exe:\r
-\r
-1. Create New Workspace  - \r
-Select from Microsoft Visual C++ toolbar file New\r
-Select from 'new' Project Tab Makefile Project name: Creds\r
-Location Y:\src\winnt\client_creds\r
-Select OK\r
-\r
-From Dialog Box 'Makefile - Step 1 of 2'\r
-command line= nmake /f"ntmakefile" install\r
-Output = y:\dest\root.client\usr\vice\etc\AFSCREDS.EXE\r
-Select NEXT\r
-\r
-Dialog Box 'Makefile - Step 2 of 2'\r
-Command line= nmake /f"ntmakefile" install\r
-Output = y:\dest\root.client\usr\vice\etc\AFSCREDS.EXE\r
-\r
-Select Finish\r
-\r
-Switch to FileView\r
-Right click on 'Source Files' and select 'Add Files to folder', select\r
-all *.cpp files.\r
-\r
-Right click on 'Header Files' and select 'Add Files to folder', select\r
-all *.h files.\r
-\r
-Right click on 'creds files' and select 'New Folder'\r
-Fill name in 'Build'\r
-\r
-From the toolbar select Build\r
-Select 'Build All'\r
-\r
-You should see the following string when the compile is finished:\r
-"afs_creds.exe - 0 errors(0), 0 warnings(s)"\r
-\r
-Press <F5> to execute afs_creds.exe.\r
-\r
-STEP M. Optional Items\r
-\r
-The build process has an error table that is compiled for many OpenAFS\r
-applications.  This table is generated by Unix based tools.  It is not\r
-normally necessary to modify this table so pre-generated source files\r
-are included in the OpenAFS source.  If you need to make modifications\r
-in these areas the Unix base tools that run on Windows can be found on\r
-the web. For example:\r
-\r
-       http://cygwin.com/\r
-\r
-Below is a short explanation how to update the error table.\r
-\r
-(1) Install flex and bison from a Unix based tool provider.\r
-\r
-(2) Make changes to the source files.\r
-\r
-There are two files in the source tree that are processed with lex\r
-and yacc on UNIX systems, src/comerr/et_lex.lex.l and\r
-src/comerr/error_table.y, that when processed produce the files\r
-et_lex.lex_nt.c, error_table_nt.c, and error_table_nt.h.\r
-\r
-Since NT does not include lex and yacc or any equivalent tools, we\r
-have provided the output files that lex and yacc produce (using Win32\r
-ports of flex and bison). This will allow builds to work for anyone\r
-who does not need to change the .l and .y files.\r
-\r
-If you do need to change et_lex.lex.l, then you will need to install\r
-Win32 port of flex on your system. Put flex.exe in a directory on the\r
-path and rebuild.\r
-\r
-If you do need to change error_table.y, then you will need to install\r
-a Win32 port of bison on your system. Put bison.exe in a directory on\r
-the path, configure bison as explained in step 5, and rebuild.\r
-\r
-You can also attempt to use other replacements for lex and yacc. This\r
-will require modifying the LEX and YACC settings in\r
-/config/NTMakefile.i386_nt40. If the replacements require different\r
-command line options than flex and bison, then you may also need to\r
-change src/comerr/NTMakefile.\r
-\r
-(3) Generate new OpenAFS binaries\r
-\r
-\r
-STEP N. Required patches for 1.2.2a and earlier releases\r
-\r
-There are two set of patches must be applied to 1.2.2a source to\r
-successfully build the binaries:\r
-\r
-(1)  Patches applied to 1.2.2a to build binaries, excluding install\r
-package.\r
-\r
-diff -Nur --exclude-from=exclude bas/src/NTMakefile upd/src/NTMakefile\r
---- bas/src/NTMakefile Wed Nov 14 19:38:06 2001\r
-+++ upd/src/NTMakefile Mon Dec  3 14:41:12 2001\r
-@@ -471,6 +471,7 @@\r
-       $(CD) $(OBJ)\$@\r
-       $(NTMAKE)\r
-       $(CD) ..\..     \r
-+      echo Build Finished Successfully\r
\r
- install: start finale\r
\r
-@@ -487,6 +488,7 @@\r
-       $(CD) ..\..\..\..\r
\r
- media: InstallShield5\r
-+      echo Install Script Finished Successfully\r
\r
\r
-(2)  Patches applied to 1.2.2a to build install package.\r
-\r
-diff -Nur --exclude-from=exclude bas/src/WINNT/afsd/NTMakefile upd/src/WINNT/afsd/NTMakefile\r
---- bas/src/WINNT/afsd/NTMakefile      Tue Nov 20 22:45:40 2001\r
-+++ upd/src/WINNT/afsd/NTMakefile      Wed Dec  5 11:42:46 2001\r
-@@ -169,8 +169,8 @@\r
-       $(EXEDIR)\tokens.exe \\r
-       $(EXEDIR)\unlog.exe $(EXEDIR)\afsd.exe $(EXEDIR)\afsd_service.exe \\r
-       $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \\r
--      $(LOGON_DLLFILE) $(LOG95_DLLFILE) \\r
--      $(EXEDIR)\afsshare.exe \\r
-+      $(LOGON_DLLFILE) \\r
-+      $(EXEDIR)\afsshare.exe \\r
-       $(DESTDIR)\bin\kpasswd.exe\r
\r
- install9X: install_headers $(CONF_DLLFILE) \\r
-\r
-diff -Nur --exclude-from=exclude bas/src/WINNT/install/InstallShield5/NTMakefile upd/src/WINNT/install/InstallShield5/NTMakefile\r
---- bas/src/WINNT/install/InstallShield5/NTMakefile    Wed Nov 14 19:38:50 2001\r
-+++ upd/src/WINNT/install/InstallShield5/NTMakefile    Mon Dec  3 16:43:08 2001\r
-@@ -60,7 +60,7 @@\r
-               $(MKDIR) $(DESTDIR)\Wininstall\PackageWeb\r
- !     ENDIF\r
-       $(DEL) /q $(DESTDIR)\Wininstall\PackageWeb\*.*\r
--      $(ISWEB)\Pftwwiz.exe $(AFSROOT)\src\winnt\install\InstallShield5\PackageWeb.pfw -s -a \r
-+      "$(ISWEB)\Pftwwiz.exe" $(AFSROOT)\src\winnt\install\InstallShield5\PackageWeb.pfw -s -a \r
- !ENDIF\r
-       xcopy /s/e/y "Media\OpenAFS\Disk Images\disk1\*.*" $(DESTDIR)\WinInstall\r
-       copy AFS_component_version_number.txt $(DESTDIR)\WinInstall\Version.txt\r
-diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC\r
---- bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC   Thu Sep  6 20:54:58 2001\r
-+++ upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC   Mon Dec  3 15:11:46 2001\r
-@@ -10,7 +10,7 @@\r
- #define APSTUDIO_HIDDEN_SYMBOLS\r
- #include "windows.h"\r
- #undef APSTUDIO_HIDDEN_SYMBOLS\r
--#include <.\sdrc.h>\r
-+#include <sdrc.h>\r
\r
- /////////////////////////////////////////////////////////////////////////////\r
- #undef APSTUDIO_READONLY_SYMBOLS\r
-diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep\r
---- bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep  Thu Sep  6 20:54:58 2001\r
-+++ upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep  Wed Dec 31 16:00:00 1969\r
-@@ -1,5 +0,0 @@\r
--# Microsoft Developer Studio Generated Dependency File, included by _IsUser.mak\r
--\r
--.\_Isuser.RC : \\r
--      ".\sdrc.h"\\r
--      \r
-diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/ntmakefile upd/src/WINNT/afs_setup_utils/_isuser/ntmakefile\r
---- bas/src/WINNT/afs_setup_utils/_isuser/ntmakefile   Mon Sep 10 09:39:50 2001\r
-+++ upd/src/WINNT/afs_setup_utils/_isuser/ntmakefile   Mon Dec  3 15:16:04 2001\r
-@@ -30,14 +30,6 @@\r
- "$(OUTDIR)" ::\r
-     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"\r
\r
--HEADERS = ".\sdrc.h"\r
--\r
--".\sdrc.h" : $(IS5ROOT)\INCLUDE\sdrc.h\r
--    $(COPY) $(IS5ROOT)\INCLUDE\sdrc.h .\r
--!   IF EXIST($(IS5ROOT)\Script\ISRT\Include\sdrc.h)\r
--    $(COPY) $(IS5ROOT)\Script\ISRT\Include\sdrc.h .\r
--!      ENDIF\r
--\r
- CPP=cl.exe\r
- CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ISUSER_EXPORTS" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c \r
\r
-@@ -85,20 +77,10 @@\r
-       "$(INTDIR)\_isuser.obj" \\r
-       "$(INTDIR)\_Isuser.res"\r
\r
--"$(OUTDIR)\_IsUser.dll" : "$(OUTDIR)" $(HEADERS) $(DEF_FILE) $(LINK32_OBJS)\r
-+"$(OUTDIR)\_IsUser.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)\r
-     $(LINK32) @<<\r
-   $(LINK32_FLAGS) $(LINK32_OBJS)\r
- <<\r
--\r
--\r
--!IF "$(NO_EXTERNAL_DEPS)" != "1"\r
--!IF EXISTS("_IsUser.dep")\r
--!INCLUDE "_IsUser.dep"\r
--!ELSE \r
--!MESSAGE Warning: cannot find "_IsUser.dep"\r
--!ENDIF \r
--!ENDIF \r
--\r
\r
- SOURCE=.\_isuser.c\r
+This software has been released under the terms of the IBM Public
+License.  For details, see the LICENSE file in the top-level source
+directory or on-line at http://www.openafs.org/dl/license10.html
+
+The document now provides a step by step procedure that takes the user 
+from a basic Windows NT/2000 workstation to an OpenAFS development 
+environment.   Details are provided so that a 'beginning' windows 
+developer can build an OpenAFS installable package for Windows NT/2000.  
+
+***********   Windows NT/2000 Build Process ****************
+
+Building OpenAFS for Windows requires configuring a Windows
+development system by installing compilation tools and header files.
+Open AFS Software development can be done on Windows NT or 2000.  The
+target system, where OpenAFS will be installed, should be either
+Windows NT or Windows 2000.  The building process is controlled by a
+nmake file that generates the necessary binaries and binds them into an
+install package.
+
+The following steps describe how to configure Windows 2000/NT:
+
+   A. Obtain a copy of the OpenAFS Source Tree
+   B. Install Compiler and Development tools.
+   C. Set up drive mappings.
+   D. Install SDK header files
+   E. Configure Environment variables
+   F. Set program version Level
+   G. Build Win2000 binaries
+   H. Install InstallShield 5.x
+   I. Build Win2000 InstallShield Package
+   J. Build Win2000 InstallShield Package for the Web
+   K. Final Results
+   L. Creating a Debug Environment
+   M. Optional Items
+   N. Required patches for 1.2.2a and earlier releases
+       
+The Software development tools with InstallShield require 900 MB
+storage.
+
+The Software development tools (without InstallShield) require 660 MB
+storage.
+
+The OpenAFS Source directory requires about 200 MB storage. The Source
+directory size includes additional space for files that will be
+generated during the build process.
+
+The following CDs are used in this example:
+       Microsoft SDK and Tools Jan 2001
+       Microsoft Visual Studio Version 6.0
+       InstallShield 5.5
+
+Different versions of above CDs can be used; however, building an
+install package for Windows NT/2000 requires InstallShield
+version 5.0 to 5.5 (version 6.0 or better will not work).  
+
+You can build all the necessary binaries without the InstallShield
+software. InstallShield is only needed to build an install package.
+
+STEP A. Obtain a copy of the Open AFS Source Tree.
+
+Transfer OpenAFS source tree onto your hardrive.  The source can be
+downloaded from the OpenAFS web site:
+       http://www.OpenAFS.org/release/snapindex.html.
+
+For this example, download source for version 1.2.2a using the
+following URL:
+http://www.openafs.org/dl/openafs/1.2.2a/openafs-1.2.2a-src.tar
+
+HINT: DailySnapShots are pre-release source trees and much more
+likely to have compilation errors. If this is your first attempt, do
+your build based on a release version of the source, e.g. 1.2.2.a. Once
+you have completed a build process successfully, you can experiment with
+other source trees.
+
+You will need an unzip utility that can expand compressed tar files.
+For example "Pkzip for Windows" from Pkware will uncompress tar files.
+(http://www.pkware.com/)
+
+Expand the downloaded tar file (openafs-1.2.2a-src.tar) into target
+directory (c:\OpenAFS), the unzip routine will expand the source into a
+subdirectory tree:
+               c:\OpenAFS\OpenAFS-1.2.2a\src
+
+Copy files NTMAKEFILE from 'src' to the AFS base directory:
+
+From a DOS command prompt window, enter the following copy commands:
+
+copy c:\OpenAFS\OpenAFS-1.2.2a\src\NTMAKEFILE c:\OpenAFS\OpenAFS-1.2.2a\.
+
+The AFS base directory should look something like the following:
+
+c:\OpenAFS\OpenAFS-1.2.2a\
+  NTMakefile
+  src
+         
+STEP B. Install compiler and development tools.
+
+Install a copy of Microsoft Visual C++ 5.0 or 6.0. The "Typical" install
+setting is sufficient.
+
+(1) You can reduce the installation size by selecting "Custom" install
+and remove all but the following Options:
+
+       Microsoft Visual C++
+       Data Access
+
+(2) When asked, Select to Register Environment Variables.
+
+(3) After rebooting you have to choice to install additional software
+packages. It is not necessary to install these packages.
+
+STEP C. Map development drive letters.
+
+The following documentation will assume you are mapping the Y: drive to
+the OpenAFS source directory and you are mapping X: drive to your
+development tools directory. Other configurations will work, including
+not mapping any drives, as long as the path assignments are consistent
+and you don't exceed the maximum environment variable length.
+
+Y: drive mapping provides a consistent directory location to build from.
+Building OpenAFS will require you to open up a command DOS prompt,
+navigate to drive Y: and execute the nmake file.  The source is based
+from Y: drive and the generated files are based from Y:\DEST.  If the OpenAFS 
+source tree is at a different location, you only need to re-map the
+Y: drive.
+
+X: drive mapping shortens the length of several Environment variables
+by mapping it to a directory where Visual Studio is installed. Although
+this step is not important when using Windows NT or 2000 as a
+development OS, it does reduce the chance of typing errors during
+the configuration phase.
+
+From a DOS command window enter the following commands:
+
+SUBST  y: c:\OpenAFS\OpenAFS-1.2.2a
+SUBST  x: "c:\Program Files\Microsoft Visual Studio\VC98"
+
+SUBST is persistent across DOS command prompts; that is, if you open up
+another DOS command prompt the mapped drives are still defined.
+However, if you reboot the mapped drives using SUBST will be lost.  
+
+If you need to remove Y: drive mapping, execute the following command
+from a DOS command prompt window:
+
+SUBST  y: /d
+
+STEP D. Install SDK header files.
+
+Files from Microsoft's Platform SDK for NT or 98 are required to
+complete a build on NT/2000.
+
+The header files that are required are found from a Microsoft SDK are:
+
+   netspi.h
+   npapi.h
+
+These files come from Microsoft DDKs/SDKs as follows:
+
+   January 1997 Windows NT Workstation DDK - /ddk/frc/network/inc/npapi.h
+   November 2001 Microsoft Platform SDK - install "samples" from "Core SDK"
+                              samples/winbase/security/winnt/logonnp/npapi.h
+   July 1998 Windows 95 DDK - net/inc/netmpr.h and net/inc/netspi.h
+   July 1999 Windows 98 DDK - src/net/inc/netmpr.h and src/net/inc/netspi.h
+                            - you need to install "Legacy and Related
+                              driver samples"
+
+To Install Platform SDK from CDROM
+       
+       Run "setup.exe default.htm" from CDROM:
+       Select Microsoft Core SDK
+       Select Sample and Source
+       Select installation path x:\SDK
+
+To Install Windows SDK from WEB:
+       http://www.microsoft.com/sdk
+
+STEP E. Configure the OpenAFS build environment.
+
+The following environment variables should be set:
+
+SET AFSDEV_LIB=%LIB%
+SET AFSROOT=Y:
+SET SYS_NAME=i386_nt40
+SET _WIN32_IE=0x400
+SET MSSDK=X:\Sdk
+SET MSTOOLS=X:\Sdk
+SET MSVCDIR=X:
+SET AFSDEV_BIN=X:\BIN
+SET AFSDEV_BUILDTYPE=FREE
+SET AFSDEV_INCLUDE=X:\Sdk\samples\winbase\security\winnt\logonNP;X:\Sdk\Include\ATL30;X:\Sdk\Include;%INCLUDE%
+
+Please do not include unnecessary spaces in AFSDEV_INLCUDE.
+
+Create a batch file (SETAFS.BAT) to make these settings that can be 
+executed when you bring up a DOS command prompt window.  Environment 
+variables are not persistent, if you close the DOS command window 
+or reboot, the environment variables are lost and they must be 
+recreated when you open a new DOS command prompt window.
+
+HINT: SET AFSDEV_BUILDTYPE=CHECKED if you want debug information
+included in your binaries.
+
+HINT: Adding drive mapping commands to the batch file makes it easy to
+establish your development environment even if you logoff.  I suggest
+adding the following lines to the beginning of the batch file:
+
+SUBST  y: /d
+SUBST  x: /d
+SUBST  y: c:\OpenAfs\OpenAFS-1.2.2a
+SUBST  x: "c:\Program Files\Microsoft Visual Studio\VC98"
+
+HINT: Windows 2000/NT provides an alternate way to set environment
+variables in System Proprieties.  These can be accessed from the system
+control panel, advanced tab, Environment Variables.  These are
+persistent and will be reset every time a DOS command prompt window is
+opened.
+
+STEP F. Set version and installation options
+
+Add a CellServDB file to install area. CellServDB contains the entries
+for the various cell names.  You can download a general purpose one
+from:
+       http://grand.central.org/dl/cellservdb/CellServDB
+then copy it to Y:\DEST\Wininstall\Config\CellServDB.GrandCentral
+
+Note: Create directory Y:\DEST\Wininstall\Config\ if it doesn't exist.
+
+Edit file Y:\src\config\NTMakefile.i386_nt40
+       AFSPRODUCT_VERSION  - Product version
+       CELLSERVDB_INSTALL - The default file name for the CellServDB
+       included in the install Package.
+       CELLNAME_DEFAULT -  The default home cell name.
+       CELLSERVDB_WEB  - The default web address to obtain CellServDB
+
+For example: in the file Y:\src\config\NTMakefile.i386_nt40 you would
+see the following:
+
+   AFSPRODUCT_VERSION=1.2.2a
+   CELLNAME_DEFAULT=home.cell.com
+   CELLSERVDB_INSTALL=CellServDB.GrandCentral
+   CELLSERVDB_WEB=http://grand.central.org/dl/cellservdb/CellServDB
+
+During the Open AFS installation process the user will be presented
+with two choices for the CellServDB: Local copy (CELLSERVDB_INSTALL) and
+one that can be downloaded from the web (CELLSERVDB_WEB).
+
+HINT: The product version number (AFSPRODUCT_VERSION) can be changed to
+create a new version number.  For example if you have added source
+changes to OpenAFS-1.2.2a and you wanted to create a new version level,
+you may want to use the following: AFSPRODUCT_VERSION=1.2.2b
+
+STEP G. Begin the build
+
+(1) From Windows 2000 open up a DOS prompt window.
+
+(2) Clean the work area.
+
+    nmake /f NTMakefile clean
+
+(3) Build the complete Windows NT/2000 development environment.
+
+    nmake /f NTMakefile install
+
+While the build is running you will see many compile warnings. This
+behavior is normal; the build process is successful as long as the build
+process doesn't terminate with an error ("nmake.exe return code 0x2")
+and it displays 'Build Finished Successfully'.
+
+STEP H. Install InstallShield (optional).
+
+In order to build an install package for OpenAFS, InstallShield 5.5
+must be installed along with InstallShield East and West
+multi-Language packs.
+
+(1) Install InstallShield (version between 5.0 and  5.5)
+
+For minimum installation choose "compact".
+
+(2) Install West Language Pack (5.5)
+
+(3) Install East Language Pack (5.5)
+
+NOTE: InstallShield's versions 6 and higher WILL NOT WORK for
+Windows NT/2000 build process.
+
+(4) Add necessary DLL's to work with the InstallShield package.
+
+Two Microsoft DLL's are missing from the InstallShield package. These
+DLL's must be copied to Y:\DEST\WinInstall\Config\:
+       SHLWAPI.DLL 
+       WININET.DLL
+
+These files are only used during the installation, and they will not 
+be left on the target machine.  They can be located at 
+%SystemRoot%\SYSTEM32.
+
+From a DOS command prompt window enter the following commands:
+
+copy %systemRoot%\System32\SHLWAPI.DLL y:\dest\wininstall\config\.
+copy %systemRoot%\System32\WININET.DLL y:\dest\wininstall\config\.
+
+(5) Add two Environment variables to the bottom of the batch file,
+SETAFS.BAT (see STEP E:).
+
+SET IS5ROOT="C:\Program Files\InstallShield\InstallShield 5.5 Professional Edition"
+SET AFSDEV_INCLUDE=%AFSDEV_INCLUDE%;%IS5ROOT%\Include
+
+STEP I.  Build Win2000 InstallShield package
+
+From the DOS command prompt window run:
+
+       Y:
+    nmake /f NTMakefile media
+
+While the build is running you will see a few compile warnings. This
+behavior is normal; the build process is successful as long as the build
+process doesn't terminate with an error ("nmake.exe return code 0x2")
+and it displays 'Install Script Finished Successfully'.
+
+STEP J.  Build Win2000 InstallShield package for the Web
+
+InstallShield's PackageForTheWeb combines the installation files into a
+single application file that will expand on execution and lead you
+through the OpenAFS installation.   
+
+Install PackageForTheWeb 3 from InstallShield
+
+Add Environment variables to the bottom of the batch file, SETAFS.BAT
+(see STEP E:).
+
+SET ISWEB="C:\Program Files\InstallShield\PackageForTheWeb 3"
+
+From the DOS command prompt window run:
+
+       Y:
+    nmake /f NTMakefile media
+
+While the build is running you will see a few compile warnings. This
+behavior is normal; the build process is successful as long as the build
+process doesn't terminate with an error ("nmake.exe return code 0x2") and
+it displays 'Install Script Finished Successfully'.
+
+HINT:  It is only necessary to run "nmake /f NTMakefile media" once, by 
+combining steps I & J.     
+
+STEP K. Final Results
+
+The build process generates its binaries in Y:\DEST. The subdirectory
+would look like the following:
+
+Y:\DEST
+       bin
+       etc
+       include
+       lib
+       root.client
+       root.server
+       WinInstall
+
+Y:\DEST\Bin - contains build utilities.
+Y:\DEST\root.client - contains Open AFS binaries
+Y:\DEST\root.server - contain Open AFS Server binaries
+Y:\DEST\WinInstall\PackageWeb\AFSforWindows.exe - is the Web install
+package for Open AFS.
+Y:\DEST\WinInstall\ - are the install package files for Open AFS
+
+Step L. Creating a Debug Environment
+
+Instructions on building a debugging environment from Visual Studio C++
+workspace.  This example give the user a way to step through the source
+code for AFSCREDS.EXE.
+
+These instructions are to be followed after you have set up the
+development environment.
+
+The following steps must be done before you can build a debug
+environment:
+
+1. Set up the development environment as described above
+2. set AFS_BUILDTYPE=CHECKED to get debug information.
+3. You must use environment variables in System Properties
+4. Do a complete build.
+
+To set the the environment variables in the System Properties:
+1. Select the 'System' icon in the control Panel
+2. Select the 'Advanced' tab
+3. Select the 'Environment Variables' button
+4. In the user area set all variables as you did above that
+were used in the setafs.bat file.
+
+To build a new work space to debug afs_creds.exe:
+
+1. Create New Workspace  - 
+Select from Microsoft Visual C++ toolbar file New
+Select from 'new' Project Tab Makefile Project name: Creds
+Location Y:\src\winnt\client_creds
+Select OK
+
+From Dialog Box 'Makefile - Step 1 of 2'
+command line= nmake /f"ntmakefile" install
+Output = y:\dest\root.client\usr\vice\etc\AFSCREDS.EXE
+Select NEXT
+
+Dialog Box 'Makefile - Step 2 of 2'
+Command line= nmake /f"ntmakefile" install
+Output = y:\dest\root.client\usr\vice\etc\AFSCREDS.EXE
+
+Select Finish
+
+Switch to FileView
+Right click on 'Source Files' and select 'Add Files to folder', select
+all *.cpp files.
+
+Right click on 'Header Files' and select 'Add Files to folder', select
+all *.h files.
+
+Right click on 'creds files' and select 'New Folder'
+Fill name in 'Build'
+
+From the toolbar select Build
+Select 'Build All'
+
+You should see the following string when the compile is finished:
+"afs_creds.exe - 0 errors(0), 0 warnings(s)"
+
+Press <F5> to execute afs_creds.exe.
+
+STEP M. Optional Items
+
+The build process has an error table that is compiled for many OpenAFS
+applications.  This table is generated by Unix based tools.  It is not
+normally necessary to modify this table so pre-generated source files
+are included in the OpenAFS source.  If you need to make modifications
+in these areas the Unix base tools that run on Windows can be found on
+the web. For example:
+
+       http://cygwin.com/
+
+Below is a short explanation how to update the error table.
+
+(1) Install flex and bison from a Unix based tool provider.
+
+(2) Make changes to the source files.
+
+There are two files in the source tree that are processed with lex
+and yacc on UNIX systems, src/comerr/et_lex.lex.l and
+src/comerr/error_table.y, that when processed produce the files
+et_lex.lex_nt.c, error_table_nt.c, and error_table_nt.h.
+
+Since NT does not include lex and yacc or any equivalent tools, we
+have provided the output files that lex and yacc produce (using Win32
+ports of flex and bison). This will allow builds to work for anyone
+who does not need to change the .l and .y files.
+
+If you do need to change et_lex.lex.l, then you will need to install
+Win32 port of flex on your system. Put flex.exe in a directory on the
+path and rebuild.
+
+If you do need to change error_table.y, then you will need to install
+a Win32 port of bison on your system. Put bison.exe in a directory on
+the path, configure bison as explained in step 5, and rebuild.
+
+You can also attempt to use other replacements for lex and yacc. This
+will require modifying the LEX and YACC settings in
+/config/NTMakefile.i386_nt40. If the replacements require different
+command line options than flex and bison, then you may also need to
+change src/comerr/NTMakefile.
+
+(3) Generate new OpenAFS binaries
+
+
+STEP N. Required patches for 1.2.2a and earlier releases
+
+There are two set of patches must be applied to 1.2.2a source to
+successfully build the binaries:
+
+(1)  Patches applied to 1.2.2a to build binaries, excluding install
+package.
+
+diff -Nur --exclude-from=exclude bas/src/NTMakefile upd/src/NTMakefile
+--- bas/src/NTMakefile Wed Nov 14 19:38:06 2001
++++ upd/src/NTMakefile Mon Dec  3 14:41:12 2001
+@@ -471,6 +471,7 @@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..     
++      echo Build Finished Successfully
+ install: start finale
+@@ -487,6 +488,7 @@
+       $(CD) ..\..\..\..
+ media: InstallShield5
++      echo Install Script Finished Successfully
+(2)  Patches applied to 1.2.2a to build install package.
+
+diff -Nur --exclude-from=exclude bas/src/WINNT/afsd/NTMakefile upd/src/WINNT/afsd/NTMakefile
+--- bas/src/WINNT/afsd/NTMakefile      Tue Nov 20 22:45:40 2001
++++ upd/src/WINNT/afsd/NTMakefile      Wed Dec  5 11:42:46 2001
+@@ -169,8 +169,8 @@
+       $(EXEDIR)\tokens.exe \
+       $(EXEDIR)\unlog.exe $(EXEDIR)\afsd.exe $(EXEDIR)\afsd_service.exe \
+       $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \
+-      $(LOGON_DLLFILE) $(LOG95_DLLFILE) \
+-      $(EXEDIR)\afsshare.exe \
++      $(LOGON_DLLFILE) \
++      $(EXEDIR)\afsshare.exe \
+       $(DESTDIR)\bin\kpasswd.exe
+ install9X: install_headers $(CONF_DLLFILE) \
+
+diff -Nur --exclude-from=exclude bas/src/WINNT/install/InstallShield5/NTMakefile upd/src/WINNT/install/InstallShield5/NTMakefile
+--- bas/src/WINNT/install/InstallShield5/NTMakefile    Wed Nov 14 19:38:50 2001
++++ upd/src/WINNT/install/InstallShield5/NTMakefile    Mon Dec  3 16:43:08 2001
+@@ -60,7 +60,7 @@
+               $(MKDIR) $(DESTDIR)\Wininstall\PackageWeb
+ !     ENDIF
+       $(DEL) /q $(DESTDIR)\Wininstall\PackageWeb\*.*
+-      $(ISWEB)\Pftwwiz.exe $(AFSROOT)\src\winnt\install\InstallShield5\PackageWeb.pfw -s -a 
++      "$(ISWEB)\Pftwwiz.exe" $(AFSROOT)\src\winnt\install\InstallShield5\PackageWeb.pfw -s -a 
+ !ENDIF
+       xcopy /s/e/y "Media\OpenAFS\Disk Images\disk1\*.*" $(DESTDIR)\WinInstall
+       copy AFS_component_version_number.txt $(DESTDIR)\WinInstall\Version.txt
+diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC
+--- bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC   Thu Sep  6 20:54:58 2001
++++ upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.RC   Mon Dec  3 15:11:46 2001
+@@ -10,7 +10,7 @@
+ #define APSTUDIO_HIDDEN_SYMBOLS
+ #include "windows.h"
+ #undef APSTUDIO_HIDDEN_SYMBOLS
+-#include <.\sdrc.h>
++#include <sdrc.h>
+ /////////////////////////////////////////////////////////////////////////////
+ #undef APSTUDIO_READONLY_SYMBOLS
+diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep
+--- bas/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep  Thu Sep  6 20:54:58 2001
++++ upd/src/WINNT/afs_setup_utils/_isuser/_IsUser.dep  Wed Dec 31 16:00:00 1969
+@@ -1,5 +0,0 @@
+-# Microsoft Developer Studio Generated Dependency File, included by _IsUser.mak
+-
+-.\_Isuser.RC : \
+-      ".\sdrc.h"\
+-      
+diff -Nur --exclude-from=exclude bas/src/WINNT/afs_setup_utils/_isuser/ntmakefile upd/src/WINNT/afs_setup_utils/_isuser/ntmakefile
+--- bas/src/WINNT/afs_setup_utils/_isuser/ntmakefile   Mon Sep 10 09:39:50 2001
++++ upd/src/WINNT/afs_setup_utils/_isuser/ntmakefile   Mon Dec  3 15:16:04 2001
+@@ -30,14 +30,6 @@
+ "$(OUTDIR)" ::
+     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+-HEADERS = ".\sdrc.h"
+-
+-".\sdrc.h" : $(IS5ROOT)\INCLUDE\sdrc.h
+-    $(COPY) $(IS5ROOT)\INCLUDE\sdrc.h .
+-!   IF EXIST($(IS5ROOT)\Script\ISRT\Include\sdrc.h)
+-    $(COPY) $(IS5ROOT)\Script\ISRT\Include\sdrc.h .
+-!      ENDIF
+-
+ CPP=cl.exe
+ CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ISUSER_EXPORTS" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+@@ -85,20 +77,10 @@
+       "$(INTDIR)\_isuser.obj" \
+       "$(INTDIR)\_Isuser.res"
+-"$(OUTDIR)\_IsUser.dll" : "$(OUTDIR)" $(HEADERS) $(DEF_FILE) $(LINK32_OBJS)
++"$(OUTDIR)\_IsUser.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+     $(LINK32) @<<
+   $(LINK32_FLAGS) $(LINK32_OBJS)
+ <<
+-
+-
+-!IF "$(NO_EXTERNAL_DEPS)" != "1"
+-!IF EXISTS("_IsUser.dep")
+-!INCLUDE "_IsUser.dep"
+-!ELSE 
+-!MESSAGE Warning: cannot find "_IsUser.dep"
+-!ENDIF 
+-!ENDIF 
+-
+ SOURCE=.\_isuser.c
index 9ac219f..adec9be 100644 (file)
@@ -5,6 +5,7 @@
 # License.  For details, see the LICENSE file in the top-level source
 # directory or online at http://www.openafs.org/dl/license10.html
 
+AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" 
 AFSDEV_NETGUI = 1
 RELDIR=WINNT\afsd
 !INCLUDE ..\..\config\NTMakefile.$(SYS_NAME)
@@ -17,6 +18,8 @@ EXEDIR = $(DESTDIR)\root.client\usr\vice\etc
 
 INCFILEDIR = $(DESTDIR)\include\afs  # header file install directory
 
+# afsdicon and below added for WINNT\extra support
+
 INCFILES =\
        $(INCFILEDIR)\afsd.h \
        $(INCFILEDIR)\cm.h \
@@ -43,10 +46,27 @@ INCFILES =\
 !IFDEF OSICRASH
        $(INCFILEDIR)\afsdcrash.h \
 !ENDIF
-       $(INCFILEDIR)\cm_dns_private.h
+       $(INCFILEDIR)\cm_dns_private.h \
+       $(INCFILEDIR)\lanahelper.h \
+       $(INCFILEDIR)\afsdicon.h \
+       $(INCFILEDIR)\cm_callback.h \
+       $(INCFILEDIR)\cm_aclent.h \
+       $(INCFILEDIR)\cm_volume.h \
+       $(INCFILEDIR)\cm_dcache.h \
+       $(INCFILEDIR)\cm_access.h \
+       $(INCFILEDIR)\cm_vnodeops.h \
+       $(INCFILEDIR)\cm_dir.h \
+       $(INCFILEDIR)\cm_utils.h \
+       $(INCFILEDIR)\cm_daemon.h \
+       $(INCFILEDIR)\cm_ioctl.h \
+       $(INCFILEDIR)\cm_dnlc.h \
+       $(INCFILEDIR)\cm_buf.h \
+       $(INCFILEDIR)\cm_freelance.h \
+    $(INCFILEDIR)\afsd_eventlog.h \
+    $(INCFILEDIR)\afsd_eventmessages.h
 
 IDLFILES =\
-       afsrpc.h $(OUT)\afsrpc_c.c
+       afsrpc.h $(OUT)\afsrpc_c.obj
 
 CONFOBJS=$(OUT)\cm_config.obj \
          $(OUT)\cm_dns.obj
@@ -94,10 +114,15 @@ AFSDOBJS=\
 !IFDEF OSICRASH
        $(OUT)\afsdcrash.obj \
 !ENDIF
-     $(OUT)\cm_freelance.obj
+    $(OUT)\cm_freelance.obj \
+    $(OUT)\lanahelper.obj  \
+    $(OUT)\afsd_eventlog.obj \
+    $(OUT)\afsd_flushvol.obj
+
+$(AFSDOBJS):
 
 $(OUT)\cm_conn.obj: cm_conn.c
-       $(C2OBJ) -DAFS_PTHREAD_ENV $**
+       $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
 
 FSOBJS=$(OUT)\fs.obj $(OUT)\fs_utils.obj
 
@@ -105,6 +130,12 @@ SLOBJS=$(OUT)\symlink.obj $(OUT)\fs_utils.obj
 
 ILIBDIR = $(DESTDIR)\lib
 
+#                                                    
+# Rules for message compiler info for logging events 
+#                                                    
+$(INCFILEDIR)\afsd_eventmessages.h:  afsd_eventmessages.mc         
+       mc afsd_eventmessages.mc                           
+                                                     
 ############################################################################
 #
 # Flags for linking LOGON DLL'S
@@ -136,6 +167,7 @@ MIDL_FLAGS=/app_config \
 CONF_DLLFILE = $(DESTDIR)\root.client\usr\vice\etc\libafsconf.dll
 
 CONF_DLLLIBS = \
+    dnsapi.lib \
     $(DESTDIR)\lib\afs\afsutil.lib \
     $(DESTDIR)\lib\afs\afsreg.lib
 
@@ -155,6 +187,7 @@ LOGON_DLLOBJS =\
        $(OUT)\afslogon.res
 
 LOGON_DLLLIBS =\
+    dnsapi.lib \
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\libafsconf.lib
 
@@ -174,6 +207,7 @@ LOG95_DLLOBJS =\
        $(OUT)\afslog95.res
 
 LOG95_DLLLIBS =\
+    dnsapi.lib \
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\libafsconf.lib
 
@@ -225,6 +259,7 @@ install_libutils: install_headers $(CONF_DLLFILE) \
 # assorted exe's
 
 EXELIBS = \
+    dnsapi.lib \
        $(DESTDIR)\lib\afs\afsauth.lib \
        $(DESTDIR)\lib\afs\afskauth.lib \
        $(DESTDIR)\lib\afs\afsprot.lib \
@@ -263,9 +298,11 @@ AFSD_EXEFILE = $(EXEDIR)\afsd.exe
 AFSD_EXELIBS =\
        largeint.lib \
        netapi32.lib \
-        mpr.lib \
+    mpr.lib \
+    dnsapi.lib \
        $(DESTDIR)\lib\libosi.lib \
        $(DESTDIR)\lib\afsrpc.lib \
+    $(DESTDIR)\lib\afsrx.lib \
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\afs\mtafsvldb.lib \
        $(DESTDIR)\lib\afs\mtafsint.lib \
@@ -282,7 +319,7 @@ $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res  $(RXOBJS)
 
 # afsd_service.exe
 $(EXEDIR)\afsd_service.exe: $(OUT)\afsd_service.obj $(AFSDOBJS) $(OUT)\afsd_service.res  $(RXOBJS)
-       $(EXECONLINK) $(AFSD_EXELIBS)
+       $(EXECONLINK) $(AFSD_EXELIBS) /NODEFAULTLIB:libc.lib /MAP
        $(EXEPREP)
 
 # fs.exe
@@ -318,18 +355,22 @@ KPASSWD_OBJS =\
 KPASSWD_LIBS =\
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\afsrpc.lib \
+    $(DESTDIR)\lib\afsrx.lib \
        $(DESTDIR)\lib\afs\afscmd.lib \
        $(DESTDIR)\lib\afsdes.lib \
        $(DESTDIR)\lib\afs\afsutil.lib
 
 $(OUT)\kpasswd.obj: $(KAUTH)/kpasswd.c
-       $(C2OBJ) -DAFS_PTHREAD_ENV $**
+       $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
 
 $(OUT)\kkids.obj: $(KAUTH)/kkids.c
-       $(C2OBJ) -DAFS_PTHREAD_ENV $**
+       $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
 
 $(OUT)\kautils.obj: $(KAUTH)/kautils.c
-       $(C2OBJ) -DAFS_PTHREAD_ENV $**
+       $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
+
+$(OUT)\kpasswd.res: $(KAUTH)\kpasswd.rc
+    $(RC) /Fo$@ $**
 
 $(DESTDIR)\bin\kpasswd.exe: $(KPASSWD_OBJS) $(KPASSWD_LIBS)
        $(DEL) $(DESTDIR)\bin\kpasswd.exe
@@ -340,30 +381,34 @@ $(DESTDIR)\bin\kpasswd.exe: $(KPASSWD_OBJS) $(KPASSWD_LIBS)
 ############################################################################
 # generate versioninfo resources
 
-$(OUT)\afsshare.res: AFS_component_version_number.h
+$(OUT)\afsshare.res: afsshare.rc AFS_component_version_number.h
 
-$(OUT)\fs.res: AFS_component_version_number.h
+$(OUT)\fs.res: fs.rc AFS_component_version_number.h
 
-$(OUT)\symlink.res: AFS_component_version_number.h
+$(OUT)\symlink.res: symlink.rc AFS_component_version_number.h
 
-$(OUT)\klog.res: AFS_component_version_number.h
+$(OUT)\klog.res: klog.rc AFS_component_version_number.h
 
-$(OUT)\tokens.res: AFS_component_version_number.h
+$(OUT)\tokens.res: tokens.rc AFS_component_version_number.h
 
-$(OUT)\unlog.res: AFS_component_version_number.h
+$(OUT)\unlog.res: unlog.rc AFS_component_version_number.h
 
-$(OUT)\afsd_service.res: AFS_component_version_number.h
+afsd_eventmessages.rc: afsd_eventmessages.h
 
-$(OUT)\afslogon.res: AFS_component_version_number.h
+$(OUT)\afsd_service.res: afsd_service.rc afsd_eventmessages.rc AFS_component_version_number.h
 
-$(OUT)\afslog95.res: AFS_component_version_number.h
+$(OUT)\afslogon.res: afslogon.rc AFS_component_version_number.h
 
-$(OUT)\libafsconf.res: AFS_component_version_number.h
+$(OUT)\afslog95.res: afslog95.rc AFS_component_version_number.h
 
+$(OUT)\libafsconf.res: libafsconf.rc AFS_component_version_number.h
+
+############################################################################
 clean::
        $(DEL) $(OUT)\*.res
        $(DEL) afsrpc.h
        $(DEL) afsrpc_?.*
+    $(DEL) afsd_eventmessages.h
        $(DEL) $(CONF_DLLFILE)
        $(DEL) $(LOGON_DLLFILE)
        $(DEL) $(LOG95_DLLFILE)
diff --git a/src/WINNT/afsd/afsd_eventlog.c b/src/WINNT/afsd/afsd_eventlog.c
new file mode 100644 (file)
index 0000000..10ecffd
--- /dev/null
@@ -0,0 +1,222 @@
+////////////////////////////////////////////////////////////////////
+//
+//
+//             E V E N T   L O G G I N G   F U N C T I O N S 
+//
+//
+////////////////////////////////////////////////////////////////////
+
+
+#include <windows.h>
+#include <stdarg.h>
+#include <string.h>
+#include "afsd_eventlog.h"
+
+#define SZSERVICEPATH          "System\\CurrentControlSet\\Services\\"
+#define SZSERVICENAME          "TransarcAFSDaemon"
+
+static CHAR    szKeyName[] = "System\\CurrentControlSet\\Services\\EventLog\\Application\\TransarcAFSDaemon";
+
+static BOOL    GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize);
+static BOOL    AddEventSource(void);
+
+static BOOL
+GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
+{
+       HKEY    hKey = NULL; 
+       UCHAR   szBuf[MAX_PATH]; 
+       DWORD   dwData = 0;
+       BOOL    bRet = TRUE;
+
+       do {
+               // Prepare path in Registry
+               memset(szBuf, '\0', MAX_PATH);
+               strcpy(szBuf, SZSERVICEPATH);
+               strcat(szBuf, "TransarcAFSDaemon");
+               
+               // Open key
+               if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey ) )
+               {               
+                       bRet = FALSE;
+                       break;
+               }
+
+               // prepare user's buffer and read into it
+               dwData = *pdwPathBufSize;
+               memset(lpPathBuf, '\0', dwData);
+               if ( RegQueryValueEx( 
+                               hKey,                   // handle to key
+                               "ImagePath",            // value name
+                               NULL,                   // reserved
+                               NULL,                   // type buffer
+                               (LPBYTE) lpPathBuf,     // data buffer
+                               &dwData))               // size of data buffer
+               {
+                       bRet = FALSE;
+                       break;
+               }
+               
+               *pdwPathBufSize = dwData;
+
+       } while (0);
+                               
+       if (hKey != NULL)
+               RegCloseKey(hKey); 
+       
+       return bRet;
+} 
+
+//
+// Ensure name for message file is in proper location in Registry.
+//
+static BOOL
+AddEventSource()
+{
+       HKEY    hKey = NULL; 
+       UCHAR   szBuf[MAX_PATH]; 
+       DWORD   dwData, dwDisposition; 
+       BOOL    bRet = TRUE;
+
+       do {
+               // Let's see if key already exists as a subkey under the 
+               // Application key in the EventLog registry key.  If not,
+               // create it.
+               if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKeyName, 0,
+                                  KEY_QUERY_VALUE, &hKey ) )
+               {               
+                       // nope - create it             
+                       if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0,
+                                           NULL, REG_OPTION_NON_VOLATILE,
+                                           KEY_ALL_ACCESS, NULL, &hKey,
+                                           &dwDisposition)) 
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+                                               
+                       // Set the name of the message file
+                       // Get "ImagePath" from TransarcAFSDaemon service
+                       memset(szBuf, '\0', MAX_PATH);
+                       dwData = MAX_PATH;
+                       GetServicePath(szBuf, &dwData);
+
+                       // Add the name to the EventMessageFile subkey. 
+                       if ( RegSetValueEx(
+                                       hKey,                   // subkey handle 
+                                       "EventMessageFile",     // value name 
+                                       0,                      // must be zero 
+                                       REG_EXPAND_SZ,          // value type 
+                                       (LPBYTE) szBuf,         // pointer to value data 
+                                       strlen(szBuf) + 1))     // length of value data
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+                       // Set the supported event types in the TypesSupported subkey. 
+                       dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
+                                               EVENTLOG_INFORMATION_TYPE; 
+                       if ( RegSetValueEx(
+                                       hKey,                   // subkey handle 
+                                       "TypesSupported",       // value name 
+                                       0,                      // must be zero 
+                                       REG_DWORD,              // value type 
+                                       (LPBYTE) &dwData,       // pointer to value data 
+                                       sizeof(DWORD)))         // length of value data
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+               }
+
+               else
+               {
+                       // key was opened - read it
+                       memset(szBuf, '\0', MAX_PATH);
+                       dwData = MAX_PATH;
+                       if ( RegQueryValueEx( 
+                                       hKey,                   // handle to key
+                                       "EventMessageFile",     // value name
+                                       NULL,                   // reserved
+                                       NULL,                   // type buffer
+                                       (LPBYTE) szBuf,         // data buffer
+                                       &dwData))               // size of data buffer
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+               }
+               
+       } while (0);
+                               
+       if (hKey != NULL)
+               RegCloseKey(hKey); 
+
+       return bRet;
+} 
+
+// Log an event with a formatted system message as the (only) substitution
+// string, from the given message ID.
+VOID
+LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID)
+{
+       LPTSTR msgBuf;
+
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+                     | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                     NULL, dwMessageID, 0, (LPTSTR)&msgBuf, 0, NULL);
+       LogEvent(wEventType, dwEventID, msgBuf, NULL);
+       LocalFree(msgBuf);
+}
+
+//
+// Use the ReportEvent API to write an entry to the system event log.
+//
+#define MAXSTRINGARGS 100
+VOID
+LogEvent(WORD wEventType, DWORD dwEventID, LPTSTR lpString, ...)
+{
+       va_list listStrings;
+       HANDLE  hEventSource;
+       LPTSTR lpStrings[MAXSTRINGARGS];
+       WORD wNumStrings;
+
+       // Ensure that our event source is properly initialized.
+       if (!AddEventSource())
+               return;
+
+       // Get a handle to the event log.
+       hEventSource = RegisterEventSource(NULL, SZSERVICENAME);
+       if (hEventSource == NULL)
+               return;
+
+       // Construct the array of substitution strings.
+       va_start(listStrings, lpString);
+       for (wNumStrings = 0;
+            lpString != NULL && wNumStrings < MAXSTRINGARGS;
+            wNumStrings++)
+       {
+               lpStrings[wNumStrings] = lpString;
+               // Advance to the next argument.
+               lpString = va_arg(listStrings, LPTSTR);
+       }
+       va_end(listStrings);
+
+       // Make sure we were not given too many args.
+       if (wNumStrings >= MAXSTRINGARGS)
+               return;
+
+       // Log the event.
+       ReportEvent(hEventSource,               // handle of event source
+                   wEventType,                 // event type
+                   0,                          // event category
+                   dwEventID,                  // event ID
+                   NULL,                       // current user's SID
+                   wNumStrings,                // strings in lpszStrings
+                   0,                          // no bytes of raw data
+                   lpStrings,                  // array of error strings
+                   NULL);                      // no raw data
+
+       DeregisterEventSource(hEventSource);
+}
diff --git a/src/WINNT/afsd/afsd_eventlog.h b/src/WINNT/afsd/afsd_eventlog.h
new file mode 100644 (file)
index 0000000..614d2d8
--- /dev/null
@@ -0,0 +1,13 @@
+// This header contains needed definitions and declarations for afsd's
+// event logging functions.
+
+#ifndef __AFSD_EVENTLOG_H_
+#define __AFSD_EVENTLOG_H_ 1
+
+// Include the event log message definitions.
+#include "afsd_eventmessages.h"
+
+VOID LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID);
+VOID LogEvent(WORD wEventType, DWORD dwEventID, LPTSTR lpString, ...);
+
+#endif /* __AFSD_EVENTLOG_H_ */
diff --git a/src/WINNT/afsd/afsd_eventmessages.mc b/src/WINNT/afsd/afsd_eventmessages.mc
new file mode 100644 (file)
index 0000000..37f86ac
--- /dev/null
@@ -0,0 +1,109 @@
+;//
+;// afsd_eventmessages.mc
+;//
+;// This file contains the message definitions for the
+;// TransarcAFSDaemon service to facilitate system event logging.
+;//
+;//
+;
+;#ifndef __AFSD_EVENTMESSAGES_H_
+;#define __AFSD_EVENTMESSAGES_H_ 1
+
+MessageIdTypedef=DWORD
+
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+               Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+               Warning=0x2:STATUS_SEVERITY_WARNING
+               Error=0x3:STATUS_SEVERITY_ERROR
+              )
+
+FacilityNames=(System=0x0:FACILITY_SYSTEM
+               Runtime=0x2:FACILITY_RUNTIME
+               Stubs=0x3:FACILITY_STUBS
+               Io=0x4:FACILITY_IO_ERROR_CODE
+              )
+
+LanguageNames=(English=0x409:MSG00409)
+
+MessageId=0x1
+Severity=Informational
+Facility=System
+SymbolicName=MSG_TIME_FLUSH_PER_VOLUME
+Language=English
+Elapsed time to flush AFS volume <%1> = %2 milliseconds.
+.
+
+MessageId=
+Severity=Informational
+Facility=System
+SymbolicName=MSG_TIME_FLUSH_TOTAL
+Language=English
+Total elapsed time to flush %1 AFS volume(s) = %2 milliseconds.
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_NO_SHARE_NAME
+Language=English
+Cannot get AFS share name to flush volumes.
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_BAD_SHARE_NAME
+Language=English
+Invalid share name %1; cannot flush volumes.
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_NO_MEMORY
+Language=English
+Insufficient memory to flush volumes.
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_OPEN_ENUM_ERROR
+Language=English
+Cannot open enumeration of network resources: %1
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_ENUM_ERROR
+Language=English
+Cannot enumerate network resources: %1
+.
+
+MessageId=
+Severity=Warning
+Facility=System
+SymbolicName=MSG_FLUSH_FAILED
+Language=English
+Failed to flush volume %1.
+.
+
+MessageId=
+Severity=Error
+Facility=System
+SymbolicName=MSG_FLUSH_IMPERSONATE_ERROR
+Language=English
+Failed to impersonate logged-on user.
+.
+
+MessageId=
+Severity=Warning
+Facility=System
+SymbolicName=MSG_FLUSH_UNEXPECTED_EVENT
+Language=English
+Flush volumes thread received unrecognized event.
+.
+
+
+;#endif /* __AFSD_EVENTMESSAGES_H_ 1 */
diff --git a/src/WINNT/afsd/afsd_eventmessages.rc b/src/WINNT/afsd/afsd_eventmessages.rc
new file mode 100644 (file)
index 0000000..6f3b1e6
--- /dev/null
@@ -0,0 +1,2 @@
+LANGUAGE 0x9,0x1
+1 11 MSG00409.bin
diff --git a/src/WINNT/afsd/afsd_flushvol.c b/src/WINNT/afsd/afsd_flushvol.c
new file mode 100644 (file)
index 0000000..d3abfbd
--- /dev/null
@@ -0,0 +1,483 @@
+//
+//     AFSD_FLUSHVOL.C
+// 
+//     Routines to handle flushing AFS volumes in response to 
+//     System Power event notification such as Hibernate request.
+//
+/////////////////////////////////////////////////////////////////////
+
+#include <afs/param.h>
+#include <afs/stds.h>
+
+#include <windows.h>
+
+#include <string.h>
+#include <setjmp.h>
+#include "afsd.h"
+#include "afsd_init.h"
+#include "smb.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include <winsock2.h>
+
+#include <osi.h>
+
+#include "afsd_flushvol.h"
+#include "afsd_eventlog.h"
+
+static FLUSHVOLTHREADINFO      gThreadInfo   = {0};
+static HANDLE                  gThreadHandle = NULL;
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// Call routine found in FS.EXE to flush volume.
+//
+// At entry, input param is UNC string for volume,
+// e.g. '\\afs\all\athena.mit.edu\user\m\h\mholiday'
+//
+// I believe that success from 'pioctl' routine
+// indicated by return value of zero (0).
+//
+afs_int32
+afsd_ServicePerformFlushVolumeCmd(char *data)
+{
+       register afs_int32 code;
+       struct ViceIoctl blob;
+
+       memset(&blob, '\0', sizeof(blob));
+       code = pioctl(data, VIOC_FLUSHVOLUME, &blob, 0);
+    
+       return code;
+}
+
+BOOL
+afsd_ServicePerformFlushVolumes()
+{
+       CONST CHAR      COLON = ':';
+       CONST CHAR      SLASH = '\\';
+       CONST DWORD     NETRESBUFSIZE = 16384;
+       CHAR            bufMessage[1024];
+       UINT            i;
+       DWORD           dwServerSize;
+       DWORD           dwRet;
+       DWORD           dwCount;
+       DWORD           dwNetResBufSize;
+       DWORD           dwTotalVols = 0;
+       DWORD           dwVolBegin, dwVolEnd;
+       DWORD           dwFlushBegin, dwFlushEnd;
+       HANDLE          hEnum;
+       LPNETRESOURCE   lpNetResBuf, lpnr;
+       PCHAR           pszShareName, pc;
+       afs_int32       afsRet = 0;
+       
+       // Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
+       // and the length of the server name prefix.
+       pszShareName = smb_GetSharename();
+       if (pszShareName == NULL)
+       {
+               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_SHARE_NAME, NULL);
+               return FALSE;
+       }
+       pc = strrchr(pszShareName, SLASH);
+       if ((pc == NULL) || ((dwServerSize = pc - pszShareName) < 3))
+       {
+               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_BAD_SHARE_NAME,
+                        pszShareName, NULL);
+               free(pszShareName);
+               return FALSE;
+       }
+
+       // Allocate a buffer to hold network resources returned by
+       // WNetEnumResource().
+       lpNetResBuf = malloc(NETRESBUFSIZE);
+       if (lpNetResBuf == NULL)
+       {
+               // Out of memory, give up now.
+               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_MEMORY, NULL);
+               free(pszShareName);
+               return FALSE;
+       }
+
+       // Initialize the flush timer.  Note that GetTickCount() returns
+       // the number of milliseconds since the system started, in a DWORD,
+       // so that the value wraps around every 49.7 days.  We do not bother
+       // to handle the case where the flush elapsed time is greater than
+       // that.
+       dwFlushBegin = GetTickCount();
+       
+       dwRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL,
+                            &hEnum);
+       if (dwRet != NO_ERROR)
+       {
+               LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_OPEN_ENUM_ERROR,
+                               dwRet);
+               free(pszShareName);
+               return FALSE;
+       }
+
+       // Loop to enumerate network resources, and flush those associated
+       // with AFS volumes.
+       while (1)
+       {
+               dwCount = -1;
+               memset(lpNetResBuf, 0, NETRESBUFSIZE);
+               dwNetResBufSize = NETRESBUFSIZE;
+               dwRet = WNetEnumResource(hEnum, &dwCount,
+                                        lpNetResBuf, &dwNetResBufSize);
+               if (dwRet != NO_ERROR)
+                       break;
+               // Iterate over the returned network resources.
+               for (i = 0, lpnr = lpNetResBuf; i < dwCount; i++, lpnr++)
+               {
+                       // Ensure resource has a remote name, and is connected.
+                       if ((lpnr->lpRemoteName == NULL) ||
+                           (lpnr->dwScope != RESOURCE_CONNECTED))
+                               continue;
+                       if ((_strnicmp(lpnr->lpRemoteName, pszShareName,
+                                      dwServerSize) == 0) &&
+                           (lpnr->lpRemoteName[dwServerSize] == SLASH))
+                       {
+                               // got one!
+                               // but we don't want to flush '\\[...]afs\all'
+                               if (_stricmp(lpnr->lpRemoteName,
+                                            pszShareName) == 0)
+                                       continue;
+                               ++dwTotalVols;
+
+                               dwVolBegin = GetTickCount();
+                               afsRet = afsd_ServicePerformFlushVolumeCmd(lpnr->lpRemoteName);
+                               dwVolEnd = GetTickCount();
+                               if (afsRet == 0)
+                               {
+                                       LogTimingEvent(MSG_TIME_FLUSH_PER_VOLUME,
+                                                      lpnr->lpRemoteName,
+                                                      dwVolEnd - dwVolBegin);
+                               }
+                               else
+                               {
+                                       LogEvent(EVENTLOG_WARNING_TYPE,
+                                                MSG_FLUSH_FAILED,
+                                                lpnr->lpRemoteName, NULL);
+                               }
+                       }
+               }
+       }
+       WNetCloseEnum(hEnum);
+       free(lpNetResBuf);
+       free(pszShareName);
+       if (dwRet != ERROR_NO_MORE_ITEMS)
+       {
+               LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_ENUM_ERROR,
+                               dwRet);
+               return FALSE;
+       }
+
+       dwFlushEnd = GetTickCount();
+       
+       // display total volume count in Event Logger
+       sprintf(bufMessage, "%d", dwTotalVols);
+       LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
+                      dwFlushEnd - dwFlushBegin);
+
+       return TRUE;
+}
+
+// Report a timing event to the system event log.
+// The lpszString1 argument is the first substitution string for the
+// given event ID.  The time argument will be converted into the
+// second substitution string.
+static VOID
+LogTimingEvent(DWORD dwEventID, LPTSTR lpString1, DWORD dwTime)
+{
+       CHAR    szTime[16];
+       
+       sprintf(szTime, "%lu", dwTime);
+       LogEvent(EVENTLOG_INFORMATION_TYPE, dwEventID, lpString1, szTime,
+                NULL);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// GetUserToken
+//
+// Obtain token for the currently logged-in user.
+//
+// This routine looks for a window which we 'know' belongs to
+// the shell, and from there we follow a route which leads to
+// getting a handle on an access token owned by the shell.
+//
+// The return value is either a handle to a suitable token,
+// or else null. 
+//
+// One of the times that this function might return null
+// is when there is no logged-in user. Other cases include
+// insufficient access to the desktop, etc. 
+//
+// Disclaimer:
+// Portions of this routine found in various newsgroups
+//
+HANDLE GetUserToken(DWORD access)
+{
+       HANDLE hTok = NULL;
+       DWORD pid = 0, tid = 0;
+
+       // Try it the easy way first - look for a window owned by the shell on
+       // our current desktop.  If we find one, use that to get the process id.
+       HWND shell = FindWindowEx(NULL, NULL, "Progman", NULL);
+       if (shell != NULL)
+       {
+               tid = GetWindowThreadProcessId(shell, &pid);
+       }
+
+       // We are possibly running on a private window station and desktop: we must
+       // switch to the default (which we suppose is where we will find the
+       // running shell).
+       else
+       {
+               HWINSTA saveWinSta = GetProcessWindowStation(); 
+               HDESK saveDesk = GetThreadDesktop(GetCurrentThreadId()); 
+               HWINSTA winSta = NULL;
+               HDESK desk = NULL;
+               BOOL changeFlag = FALSE;
+               BOOL dummy = saveWinSta != NULL &&
+                                        saveDesk != NULL &&
+                                        (winSta = OpenWindowStation("WinSta0", FALSE,
+                                                                       MAXIMUM_ALLOWED)) != NULL &&
+                                        (changeFlag = SetProcessWindowStation(winSta)) != 0 &&
+                                        (desk = OpenDesktop("Default", 0, FALSE,
+                                                                       MAXIMUM_ALLOWED)) != NULL &&
+                                        SetThreadDesktop(desk) != 0;
+
+               // Now find the window and process on this desktop
+               shell = FindWindowEx(NULL, NULL, "Progman", NULL);
+               if (shell != NULL) 
+               {
+                       tid = GetWindowThreadProcessId(shell, &pid);
+               }
+
+               // Restore our own window station and desktop
+               if (changeFlag)
+               {
+                       SetProcessWindowStation(saveWinSta);
+                       SetThreadDesktop(saveDesk);
+               }
+
+               // Close temporary objects
+               if (winSta != NULL)
+                       CloseWindowStation(winSta);
+               if (desk != NULL) 
+                       CloseDesktop(desk);
+       }
+
+       //
+       // If we have a process id, use that to get the process handle and 
+       // from there the process' access token.
+       //
+       if (pid != 0)
+       {
+               HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+               if (hProc != NULL)
+               {
+                       OpenProcessToken(hProc, access, &hTok) || (hTok = NULL);
+                       CloseHandle(hProc);
+               }
+       }
+
+       // Return token if we got one
+       return hTok;
+}
+
+// impersonate logged-on user as client
+BOOL
+ImpersonateClient()
+{
+       DWORD   dwDesiredAccess = TOKEN_ALL_ACCESS;
+       HANDLE  hUserToken = GetUserToken(dwDesiredAccess);
+       
+       if (hUserToken == NULL)
+               return FALSE;
+       if (ImpersonateLoggedOnUser(hUserToken) == 0)
+       {
+               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_IMPERSONATE_ERROR,
+                        NULL);
+               return FALSE;
+       }
+       return TRUE;
+}
+       
+/////////////////////////////////////////////////////////////////////
+//
+// Thread proc
+//
+DWORD WINAPI 
+afsd_ServiceFlushVolumesThreadProc(LPVOID lpParam)
+{
+       FLUSHVOLTHREADINFO ThreadInfo;
+       PFLUSHVOLTHREADINFO pThreadInfo = (PFLUSHVOLTHREADINFO) lpParam; 
+       HANDLE  arHandles[2] = {0};
+       DWORD   dwWaitState = 0;
+
+       // thread running - get handles
+       ThreadInfo.hEventPowerEvent = pThreadInfo->hEventPowerEvent;
+       ThreadInfo.hEventResumeMain = pThreadInfo->hEventResumeMain;
+       ThreadInfo.hEventTerminate  = pThreadInfo->hEventTerminate;
+
+       // setup to wait
+       arHandles[0] = ThreadInfo.hEventTerminate;
+       arHandles[1] = ThreadInfo.hEventPowerEvent;
+
+       // do stuff ..
+       while (1)
+       {
+               // wait for an event to happen
+               dwWaitState = WaitForMultipleObjectsEx(2, arHandles, FALSE, INFINITE, FALSE);
+
+               switch (dwWaitState)
+               {
+               case WAIT_OBJECT_0:
+                       // termination signaled
+                       RevertToSelf();
+                       ExitThread(0);
+                       break;
+
+               case WAIT_OBJECT_0+1:
+                       // Power event 
+                       // - flush 'em!
+                       if (ImpersonateClient())
+                       {
+                               afsd_ServicePerformFlushVolumes();
+                       }
+                       // acknowledge event
+                       ResetEvent(ThreadInfo.hEventPowerEvent);
+                       break;
+
+               case WAIT_ABANDONED_0:
+               case WAIT_ABANDONED_0+1:
+               case WAIT_IO_COMPLETION:
+               case WAIT_TIMEOUT:
+                       // sno*
+                       LogEvent(EVENTLOG_WARNING_TYPE,
+                                MSG_FLUSH_UNEXPECTED_EVENT, NULL);
+                       break;
+               
+               }       // end switch
+
+               // signal back to waiting mainline
+               SetEvent(ThreadInfo.hEventResumeMain);
+
+       }       // end while
+       
+       // I suppose we never get here
+       ExitThread(0);
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+// Mainline thread routines
+//
+
+VOID   
+CheckAndCloseHandle(HANDLE thisHandle)
+{
+       if (thisHandle != NULL)
+       {
+               CloseHandle(thisHandle);
+               thisHandle = NULL;
+       }
+}
+
+//
+// Thread Creation
+//
+BOOL
+PowerNotificationThreadCreate()
+{
+       BOOL    bSuccess = FALSE;
+       DWORD   dwThreadId = 0;
+       
+       do 
+       {
+               // create power event notification event
+               // bManualReset=TRUE, bInitialState=FALSE
+               gThreadInfo.hEventPowerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+               if (gThreadInfo.hEventPowerEvent == NULL)
+                       break;                  
+
+               // create mainline resume event
+               // bManualReset=FALSE, bInitialState=FALSE
+               gThreadInfo.hEventResumeMain = CreateEvent(NULL, FALSE, FALSE, NULL);
+               if (gThreadInfo.hEventResumeMain == NULL)
+                       break;                  
+
+               // create thread terminate event
+               // bManualReset=FALSE, bInitialState=FALSE
+               gThreadInfo.hEventTerminate = CreateEvent(NULL, FALSE, FALSE, NULL);
+               if (gThreadInfo.hEventTerminate == NULL)
+                       break;                  
+
+               // good so far - create thread
+               gThreadHandle = CreateThread(NULL, 0,
+                                                       afsd_ServiceFlushVolumesThreadProc,
+                                                       (LPVOID) &gThreadInfo,
+                                                       0, &dwThreadId);
+               
+               if (!gThreadHandle)
+                       break;
+
+               bSuccess = TRUE;
+
+       } while (0);
+
+
+       if (!bSuccess)
+       {
+               CheckAndCloseHandle(gThreadInfo.hEventPowerEvent);
+               CheckAndCloseHandle(gThreadInfo.hEventResumeMain);
+               CheckAndCloseHandle(gThreadInfo.hEventTerminate);
+               CheckAndCloseHandle(gThreadHandle);
+       }
+               
+       return bSuccess;
+}
+
+//
+// Thread Notification
+//
+BOOL
+PowerNotificationThreadNotify()
+{
+       DWORD           dwRet = 0;
+       BOOL            bRet  = FALSE;
+
+       // Notify thread of power event, and wait 19 seconds
+       dwRet = SignalObjectAndWait(
+                               gThreadInfo.hEventPowerEvent,   // object to signal
+                               gThreadInfo.hEventResumeMain,   // object to watch
+                               19*1000,                                                // timeout (ms)
+                               FALSE                                                   // alertable
+                               );
+
+       if (dwRet == WAIT_OBJECT_0)
+               bRet = TRUE;
+
+       return bRet;
+}
+
+//
+// Thread Termination
+//
+VOID
+PowerNotificationThreadExit()
+{
+       // ExitThread
+       if (gThreadHandle)
+       {
+               SetEvent(gThreadInfo.hEventTerminate);
+               CloseHandle(gThreadHandle);
+       }
+}
+
diff --git a/src/WINNT/afsd/afsd_flushvol.h b/src/WINNT/afsd/afsd_flushvol.h
new file mode 100644 (file)
index 0000000..ca63261
--- /dev/null
@@ -0,0 +1,45 @@
+//
+//     AFSD_FLUSHVOL.H
+// 
+//     Include file for routines that handle flushing AFS volumes
+//     in response to System Power event notification such as
+//     Hibernate request.
+//
+/////////////////////////////////////////////////////////////////////
+
+#ifndef _AFSD_FLUSHVOL_H_
+#define _AFSD_FLUSHVOL_H_
+
+#include <Winnetwk.h>
+#include "fs_utils.h"
+
+// handles 
+typedef struct _tagFLUSHVOLTHREADINFO {
+       HANDLE  hEventPowerEvent;
+       HANDLE  hEventResumeMain;
+       HANDLE  hEventTerminate;
+} FLUSHVOLTHREADINFO, *PFLUSHVOLTHREADINFO;
+
+// invokes fs.exe pioctl
+static afs_int32       afsd_ServicePerformFlushVolumeCmd(char *data);
+
+// thread callback
+static DWORD WINAPI afsd_ServiceFlushVolumesThreadProc(LPVOID lpParameter);
+
+// helper function
+static VOID    CheckAndCloseHandle(HANDLE thisHandle);
+
+// thread construction/notification/destruction
+BOOL   PowerNotificationThreadCreate(VOID);
+BOOL   PowerNotificationThreadNotify(VOID);
+VOID   PowerNotificationThreadExit(VOID);
+
+// impersonation helper(s)
+static HANDLE  GetUserToken(DWORD access);
+static BOOL    ImpersonateClient(void);
+
+// event logging
+static VOID LogTimingEvent(DWORD dwEventID, LPTSTR lpString1, DWORD dwTime);
+
+#endif // _AFSD_FLUSHVOL_H_
+
index d7f351e..e4949a8 100644 (file)
 
 #include "smb.h"
 #include "cm_rpc.h"
+#include "lanahelper.h"
 
-extern int RXAFSCB_ExecuteRequest();
-extern int RXSTATS_ExecuteRequest();
+extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
+extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
 
 extern afs_int32 cryptall;
 
@@ -130,6 +131,9 @@ afsi_log(char *pattern, ...)
         sprintf(u, "%s: %s\n", t, s);
         if (afsi_file != INVALID_HANDLE_VALUE)
             WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
+#ifdef NOTSERVICE
+        printf("%s", u);
+#endif 
     } else {
         if (afsi_file != INVALID_HANDLE_VALUE)
             WriteFile(afsi_file, s, strlen(s), &zilch, NULL);
@@ -175,6 +179,7 @@ int afsd_InitCM(char **reasonP)
        long stats;
        long traceBufSize;
        long ltt, ltto;
+    long rx_mtu, rx_nojumbo;
        char rootCellName[256];
        struct rx_service *serverp;
        static struct rx_securityClass *nullServerSecurityClassp;
@@ -225,12 +230,15 @@ int afsd_InitCM(char **reasonP)
        dummyLen = sizeof(LANadapter);
        code = RegQueryValueEx(parmKey, "LANadapter", NULL, NULL,
                                (BYTE *) &LANadapter, &dummyLen);
-       if (code == ERROR_SUCCESS)
+       if (code == ERROR_SUCCESS) {
                afsi_log("LAN adapter number %d", LANadapter);
-       else {
+        if (LANadapter < 0 || LANadapter > MAX_LANA)
+            LANadapter = -1;
+       } else {
                LANadapter = -1;
+    }
+    if ( LANadapter == -1 )
                afsi_log("Default LAN adapter number");
-       }
 
        dummyLen = sizeof(cacheSize);
        code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
@@ -450,33 +458,78 @@ int afsd_InitCM(char **reasonP)
         cm_NetBiosName[0] = 0;   /* default off */
     }
 
+    dummyLen = sizeof(smb_hideDotFiles);
+    code = RegQueryValueEx(parmKey, "HideDotFiles", NULL, NULL,
+                           (BYTE *) &smb_hideDotFiles, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        smb_hideDotFiles = 1; /* default on */
+    }
+    afsi_log("Dot files/dirs will %sbe marked hidden",
+              smb_hideDotFiles ? "" : "not ");
+
+    dummyLen = sizeof(smb_maxMpxRequests);
+    code = RegQueryValueEx(parmKey, "MaxMpxRequests", NULL, NULL,
+                           (BYTE *) &smb_maxMpxRequests, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        smb_maxMpxRequests = 50;
+    }
+    afsi_log("Maximum number of multiplexed sessions is %d", smb_maxMpxRequests);
+
+    dummyLen = sizeof(smb_maxVCPerServer);
+    code = RegQueryValueEx(parmKey, "MaxVCPerServer", NULL, NULL,
+                           (BYTE *) &smb_maxVCPerServer, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        smb_maxVCPerServer = 100;
+    }
+    afsi_log("Maximum number of VCs per server is %d", smb_maxVCPerServer);
+
+    dummyLen = sizeof(rx_nojumbo);
+    code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
+                           (BYTE *) &rx_nojumbo, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        rx_nojumbo = 0;
+    }
+    if(rx_nojumbo)
+        afsi_log("RX Jumbograms are disabled");
+
+    dummyLen = sizeof(rx_mtu);
+    code = RegQueryValueEx(parmKey, "RxMaxMTU", NULL, NULL,
+                           (BYTE *) &rx_mtu, &dummyLen);
+    if (code != ERROR_SUCCESS || !rx_mtu) {
+        rx_mtu = -1;
+    }
+    if(rx_mtu != -1)
+        afsi_log("RX maximum MTU is %d", rx_mtu);
+
        RegCloseKey (parmKey);
 
        /* setup early variables */
        /* These both used to be configurable. */
        smb_UseV3 = 1;
-        buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
+    buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
 
        /* turn from 1024 byte units into memory blocks */
-        cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
+    cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
         
        /* setup and enable debug log */
        afsd_logp = osi_LogCreate("afsd", traceBufSize);
        afsi_log("osi_LogCreate log addr %x", (int)afsd_logp);
-        osi_LogEnable(afsd_logp);
+    osi_LogEnable(afsd_logp);
        logReady = 1;
 
+    osi_Log0(afsd_logp, "Log init");
+
        /* get network related info */
        cm_noIPAddr = CM_MAXINTERFACE_ADDR;
        code = syscfg_GetIFInfo(&cm_noIPAddr,
-                               cm_IPAddr, cm_SubnetMask,
-                               cm_NetMtu, cm_NetFlags);
+                            cm_IPAddr, cm_SubnetMask,
+                            cm_NetMtu, cm_NetFlags);
 
        if ( (cm_noIPAddr <= 0) || (code <= 0 ) )
            afsi_log("syscfg_GetIFInfo error code %d", code);
        else
            afsi_log("First Network address %x SubnetMask %x",
-                    cm_IPAddr[0], cm_SubnetMask[0]);
+                 cm_IPAddr[0], cm_SubnetMask[0]);
 
        /*
         * Save client configuration for GetCacheConfig requests
@@ -491,9 +544,16 @@ int afsd_InitCM(char **reasonP)
        cm_initParams.setTime = 0;
        cm_initParams.memCache = 0;
 
+    /* Set RX parameters before initializing RX */
+    if ( rx_nojumbo )
+        rx_SetNoJumbo();
+
+    if ( rx_mtu != -1 )
+        rx_SetMaxMTU(rx_mtu);
+
        /* initialize RX, and tell it to listen to port 7001, which is used for
-         * callback RPC messages.
-         */
+     * callback RPC messages.
+     */
        code = rx_Init(htons(7001));
        afsi_log("rx_Init code %x", code);
        if (code != 0) {
@@ -506,8 +566,8 @@ int afsd_InitCM(char **reasonP)
 
        /* create an unauthenticated service #1 for callbacks */
        nullServerSecurityClassp = rxnull_NewServerSecurityObject();
-        serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
-               RXAFSCB_ExecuteRequest);
+    serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
+                            RXAFSCB_ExecuteRequest);
        afsi_log("rx_NewService addr %x", (int)serverp);
        if (serverp == NULL) {
                *reasonP = "unknown error";
@@ -515,16 +575,16 @@ int afsd_InitCM(char **reasonP)
        }
 
        nullServerSecurityClassp = rxnull_NewServerSecurityObject();
-        serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
-               &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
+    serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
+                            &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
        afsi_log("rx_NewService addr %x", (int)serverp);
        if (serverp == NULL) {
                *reasonP = "unknown error";
                return -1;
        }
         
-        /* start server threads, *not* donating this one to the pool */
-        rx_StartServer(0);
+    /* start server threads, *not* donating this one to the pool */
+    rx_StartServer(0);
        afsi_log("rx_StartServer");
 
        /* init user daemon, and other packages */
@@ -534,21 +594,21 @@ int afsd_InitCM(char **reasonP)
 
        cm_InitConn();
 
-        cm_InitCell();
-        
-        cm_InitServer();
+    cm_InitCell();
         
-        cm_InitVolume();
+    cm_InitServer();
         
-        cm_InitIoctl();
+    cm_InitVolume();
+
+    cm_InitIoctl();
         
-        smb_InitIoctl();
+    smb_InitIoctl();
         
-        cm_InitCallback();
+    cm_InitCallback();
         
-        cm_InitSCache(stats);
+    cm_InitSCache(stats);
         
-        code = cm_InitDCache(0, cacheBlocks);
+    code = cm_InitDCache(0, cacheBlocks);
        afsi_log("cm_InitDCache code %x", code);
        if (code != 0) {
                *reasonP = "error initializing cache";
@@ -556,28 +616,33 @@ int afsd_InitCM(char **reasonP)
        }
 
 #ifdef AFS_AFSDB_ENV
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x500
        if (cm_InitDNS(cm_dnsEnabled) == -1)
          cm_dnsEnabled = 0;  /* init failed, so deactivate */
        afsi_log("cm_InitDNS %d", cm_dnsEnabled);
 #endif
+#endif
 
        code = cm_GetRootCellName(rootCellName);
-       afsi_log("cm_GetRootCellName code %d rcn %s", code,
-                (code ? "<none>" : rootCellName));
-       if (code != 0 && !cm_freelanceEnabled) {
+       afsi_log("cm_GetRootCellName code %d, cm_freelanceEnabled= %d, rcn= %s", 
+             code, cm_freelanceEnabled, (code ? "<none>" : rootCellName));
+       if (code != 0 && !cm_freelanceEnabled) 
+    {
            *reasonP = "can't find root cell name in afsd.ini";
            return -1;
+    }
+    else if (cm_freelanceEnabled)
+        cm_rootCellp = NULL;
+
+    if (code == 0 && !cm_freelanceEnabled) 
+    {
+        cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
+        afsi_log("cm_GetCell addr %x", (int)cm_rootCellp);
+        if (cm_rootCellp == NULL) 
+        {
+            *reasonP = "can't find root cell in afsdcell.ini";
+            return -1;
         }
-        else if (cm_freelanceEnabled)
-          cm_rootCellp = NULL;
-
-        if (code == 0 && !cm_freelanceEnabled) {
-         cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
-          afsi_log("cm_GetCell addr %x", (int)cm_rootCellp);
-         if (cm_rootCellp == NULL) {
-           *reasonP = "can't find root cell in afsdcell.ini";
-           return -1;
-         }
        }
 
 #ifdef AFS_FREELANCE_CLIENT
@@ -597,30 +662,30 @@ int afsd_InitDaemons(char **reasonP)
 
        /* this should really be in an init daemon from here on down */
 
-        if (!cm_freelanceEnabled) {
-          code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
-                                    &req, CM_FLAG_CREATE, &cm_rootVolumep);
-          afsi_log("cm_GetVolumeByName code %x root vol %x", code,
-                   (code ? (cm_volume_t *)-1 : cm_rootVolumep));
-          if (code != 0) {
+    if (!cm_freelanceEnabled) {
+        code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
+                                  &req, CM_FLAG_CREATE, &cm_rootVolumep);
+        afsi_log("cm_GetVolumeByName code %x root vol %x", code,
+                 (code ? (cm_volume_t *)-1 : cm_rootVolumep));
+        if (code != 0) {
             *reasonP = "can't find root volume in root cell";
             return -1;
-          }
         }
+    }
 
        /* compute the root fid */
        if (!cm_freelanceEnabled) {
-         cm_rootFid.cell = cm_rootCellp->cellID;
-         cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
-         cm_rootFid.vnode = 1;
-         cm_rootFid.unique = 1;
+        cm_rootFid.cell = cm_rootCellp->cellID;
+        cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
+        cm_rootFid.vnode = 1;
+        cm_rootFid.unique = 1;
        }
        else
-         cm_FakeRootFid(&cm_rootFid);
+        cm_FakeRootFid(&cm_rootFid);
         
-        code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
+    code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
        afsi_log("cm_GetSCache code %x scache %x", code,
-                (code ? (cm_scache_t *)-1 : cm_rootSCachep));
+             (code ? (cm_scache_t *)-1 : cm_rootSCachep));
        if (code != 0) {
                *reasonP = "unknown error";
                return -1;
@@ -636,27 +701,49 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
 {
        char hostName[200];
        char *ctemp;
+    lana_number_t lana;
 
        /* Do this last so that we don't handle requests before init is done.
      * Here we initialize the SMB listener.
      */
-    if (!cm_NetBiosName[0])
-    {
-        strcpy(hostName, cm_HostName);
-        ctemp = strchr(hostName, '.'); /* turn ntdfs.* into ntdfs */
-        if (ctemp) *ctemp = 0;
+    if (LANadapter == -1) {
+        /* Find the default LAN adapter to use.  First look for
+         * the adapter named AFS; otherwise, unless we are doing
+         * gateway service, look for any valid loopback adapter.
+         */
+        lana = lana_FindLanaByName("AFS");
+        if (lana == LANA_INVALID && !isGateway)
+            lana = lana_FindLoopback();
+        if (lana != LANA_INVALID)
+            LANadapter = lana;
+    }
+    afsi_log("Lana %d", (int) lana);
+    /* If we are using a loopback adapter, we can use the preferred
+     * (but non-unique) server name; otherwise, we must fall back to
+     * the <machine>-AFS name.
+     */
+    if (LANadapter >= 0 && lana_IsLoopback((lana_number_t) LANadapter)) {
+        if ( cm_NetBiosName[0] )
+            strcpy(hostName, cm_NetBiosName);
+        else
+            strcpy(hostName, "AFS");
+    } else {
+        if (!cm_NetBiosName[0])
+        {
+            strcpy(hostName, cm_HostName);
+            ctemp = strchr(hostName, '.');     /* turn ntdfs.* into ntdfs */
+            if (ctemp) *ctemp = 0;
             hostName[11] = 0; /* ensure that even after adding the -A, we
                                * leave one byte free for the netbios server
                                * type.
                                */
-        strcat(hostName, "-AFS");
-    } else {
-        strcpy(hostName, cm_NetBiosName);
+            strcat(hostName, "-AFS");
+        } else {
+            strcpy(hostName, cm_NetBiosName);
+        }
+        _strupr(hostName);
     }
-    _strupr(hostName);
-
-    smb_Init(afsd_logp, hostName, smb_UseV3, LANadapter, numSvThreads, 
-             aMBfunc);
+    smb_Init(afsd_logp, hostName, smb_UseV3, LANadapter, numSvThreads, aMBfunc);
        afsi_log("smb_Init");
 
        return 0;
index 3e491b4..c3013a9 100644 (file)
 #include <crtdbg.h>
 #endif
 
+/*
+// The following is defined if you want to receive Power notifications,
+// including Hibernation, and also subsequent flushing of AFS volumes
+//
+// #define REGISTER_POWER_NOTIFICATIONS
+//
+// Check
+*/
+#include "afsd_flushvol.h"
+
 extern void afsi_log(char *pattern, ...);
 
 HANDLE WaitToTerminate;
@@ -88,54 +98,140 @@ static int DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
 static SERVICE_STATUS          ServiceStatus;
 static SERVICE_STATUS_HANDLE   StatusHandle;
 
-void afsd_ServiceControlHandler(DWORD ctrlCode)
+DWORD
+afsd_ServiceFlushVolume(DWORD dwlpEventData)
+{
+    DWORD   dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
+
+    /*
+    **  If UI bit is not set, user interaction is not possible
+    **      BUT, since we are a NON-interactive service, and therefore
+    **  have NO user I/O, it doesn't much matter.
+    **  This benign code left here as example of how to find this out
+    */
+    BOOL bUI = (dwlpEventData & 1);
+
+    /* flush volume */
+    if ( PowerNotificationThreadNotify() )
+    {
+        dwRet = NO_ERROR;
+    }
+
+    else
+    {
+        /* flush was unsuccessful, or timeout - deny shutdown */
+        dwRet = ERROR_NETWORK_BUSY;
+    }
+
+    /*      to deny hibernate, simply return
+    //      any value besides NO_ERROR.
+    //      For example:
+    //      dwRet = ERROR_NETWORK_BUSY;
+    */
+
+    return dwRet;
+}
+
+/*
+**    Extended ServiceControlHandler that provides Event types
+**    for monitoring Power events, for example.
+*/
+DWORD
+afsd_ServiceControlHandlerEx(
+              DWORD  ctrlCode,
+              DWORD  dwEventType,
+              LPVOID lpEventData,
+              LPVOID lpContext
+              )
 {
        HKEY parmKey;
        DWORD dummyLen, doTrace;
        long code;
+    DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
+
+       switch (ctrlCode) 
+    {
+    case SERVICE_CONTROL_STOP:
+        /* Shutdown RPC */
+        RpcMgmtStopServerListening(NULL);
+
+        /* Force trace if requested */
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                            AFSConfigKeyName,
+                            0, KEY_QUERY_VALUE, &parmKey);
+        if (code != ERROR_SUCCESS)
+            goto doneTrace;
+
+        dummyLen = sizeof(doTrace);
+        code = RegQueryValueEx(parmKey, "TraceOnShutdown",
+                               NULL, NULL,
+                               (BYTE *) &doTrace, &dummyLen);
+        RegCloseKey (parmKey);
+        if (code != ERROR_SUCCESS)
+            doTrace = 0;
+        if (doTrace)
+            afsd_ForceTrace(FALSE);
+
+      doneTrace:
+        ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 1;
+        ServiceStatus.dwWaitHint = 10000;
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+        SetEvent(WaitToTerminate);
+        dwRet = NO_ERROR;
+        break;
+
+    case SERVICE_CONTROL_INTERROGATE:
+        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 0;
+        ServiceStatus.dwWaitHint = 0;
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+        dwRet = NO_ERROR;
+        break;
 
-       switch (ctrlCode) {
-               case SERVICE_CONTROL_STOP:
-                       /* Shutdown RPC */
-                       RpcMgmtStopServerListening(NULL);
-
-                       /* Force trace if requested */
-                       code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                                           AFSConfigKeyName,
-                                           0, KEY_QUERY_VALUE, &parmKey);
-                       if (code != ERROR_SUCCESS)
-                               goto doneTrace;
-
-                       dummyLen = sizeof(doTrace);
-                       code = RegQueryValueEx(parmKey, "TraceOnShutdown",
-                                               NULL, NULL,
-                                               (BYTE *) &doTrace, &dummyLen);
-                       RegCloseKey (parmKey);
-                       if (code != ERROR_SUCCESS)
-                               doTrace = 0;
-                       if (doTrace)
-                               afsd_ForceTrace(FALSE);
-
-doneTrace:
-                       ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
-                       ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                       ServiceStatus.dwCheckPoint = 1;
-                       ServiceStatus.dwWaitHint = 10000;
-                       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-                       SetServiceStatus(StatusHandle, &ServiceStatus);
-                       SetEvent(WaitToTerminate);
-                       break;
-               case SERVICE_CONTROL_INTERROGATE:
-                       ServiceStatus.dwCurrentState = SERVICE_RUNNING;
-                       ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                       ServiceStatus.dwCheckPoint = 0;
-                       ServiceStatus.dwWaitHint = 0;
-                       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-                       SetServiceStatus(StatusHandle, &ServiceStatus);
-                       break;
                /* XXX handle system shutdown */
                /* XXX handle pause & continue */
-       }
+               case SERVICE_CONTROL_POWEREVENT:                                              
+               {                                                                                     
+                       /*                                                                                
+            ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST               
+                       **      Return NO_ERROR == return TRUE for that message, i.e. accept request          
+                       **      Return any error code to deny request,                                        
+                       **      i.e. as if returning BROADCAST_QUERY_DENY                                     
+                       */                                                                                
+                       switch((int) dwEventType)                                                         
+            {                                                                               
+                       case PBT_APMQUERYSUSPEND:                                                         
+                       case PBT_APMQUERYSTANDBY:                                                         
+                                                                                            
+#ifdef REGISTER_POWER_NOTIFICATIONS                                                                  
+                               /* handle event */                                                            
+                               dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);                         
+#else                                                                                       
+                               dwRet = NO_ERROR;                                                             
+#endif                                                                                      
+                               break;                                                                        
+                                                                                                                         
+            /* allow remaining case PBT_WhatEver */                                           
+                       case PBT_APMSUSPEND:                                                              
+                       case PBT_APMSTANDBY:                                                              
+                       case PBT_APMRESUMECRITICAL:                                                       
+                       case PBT_APMRESUMESUSPEND:                                                        
+                       case PBT_APMRESUMESTANDBY:                                                        
+                       case PBT_APMBATTERYLOW:                                                           
+                       case PBT_APMPOWERSTATUSCHANGE:                                                    
+                       case PBT_APMOEMEVENT:                                                             
+                       case PBT_APMRESUMEAUTOMATIC:                                                      
+                       default:                                                                          
+                               dwRet = NO_ERROR;                                                             
+            }
+        }
+    }          /* end switch(ctrlCode) */                                                        
+       return dwRet;   
 }
 
 #if 1
@@ -205,7 +301,7 @@ typedef BOOL ( APIENTRY * AfsdInitHook )(void);
 #define AFSD_INIT_HOOK "AfsdInitHook"
 #define AFSD_HOOK_DLL  "afsdhook.dll"
 
-void afsd_Main()
+void afsd_Main(DWORD argc, LPTSTR *argv)
 {
        long code;
        char *reason;
@@ -226,18 +322,22 @@ void afsd_Main()
        WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
 
 #ifndef NOTSERVICE
-       StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME,
-                       (LPHANDLER_FUNCTION) afsd_ServiceControlHandler);
+       StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME,
+                       (LPHANDLER_FUNCTION_EX) afsd_ServiceControlHandlerEx,
+                                                 NULL /* user context */
+                                                 );
 
        ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
        ServiceStatus.dwServiceSpecificExitCode = 0;
        ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
        ServiceStatus.dwWin32ExitCode = NO_ERROR;
        ServiceStatus.dwCheckPoint = 1;
-       ServiceStatus.dwWaitHint = 15000;
-       ServiceStatus.dwControlsAccepted = 0;
+       ServiceStatus.dwWaitHint = 30000;
+    /* accept Power Events */
+       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
        SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
+
     {       
     HANDLE h; char *ptbuf[1];
     h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
@@ -246,6 +346,11 @@ void afsd_Main()
     DeregisterEventSource(h);
     }
 
+#ifdef REGISTER_POWER_NOTIFICATIONS
+    /* create thread used to flush cache */
+    PowerNotificationThreadCreate();
+#endif
+
        afsi_start();
 
     /* allow an exit to be called prior to any initialization */
@@ -294,10 +399,20 @@ void afsd_Main()
                if (code != 0)
                        osi_panic(reason, __FILE__, __LINE__);
 
+#ifndef NOTSERVICE
+        ServiceStatus.dwCheckPoint++;
+        ServiceStatus.dwWaitHint -= 5000;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+#endif
                code = afsd_InitDaemons(&reason);
                if (code != 0)
                        osi_panic(reason, __FILE__, __LINE__);
 
+#ifndef NOTSERVICE
+        ServiceStatus.dwCheckPoint++;
+        ServiceStatus.dwWaitHint -= 5000;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+#endif
                code = afsd_InitSMB(&reason, DummyMessageBox);
                if (code != 0)
                        osi_panic(reason, __FILE__, __LINE__);
@@ -307,7 +422,9 @@ void afsd_Main()
                ServiceStatus.dwWin32ExitCode = NO_ERROR;
                ServiceStatus.dwCheckPoint = 0;
                ServiceStatus.dwWaitHint = 0;
-               ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+        /* accept Power events */
+               ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
                SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
         {
@@ -338,12 +455,21 @@ void afsd_Main()
        ServiceStatus.dwCheckPoint = 0;
        ServiceStatus.dwWaitHint = 0;
        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+    /* also now accept Power events - shutdown maybe? */
+       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+#ifdef REGISTER_POWER_NOTIFICATIONS
+       /* terminate thread used to flush cache */
+       PowerNotificationThreadExit();
+#endif
+
        SetServiceStatus(StatusHandle, &ServiceStatus);
 }
 
 DWORD __stdcall afsdMain_thread(void* notUsed)
 {
-       afsd_Main();
+       afsd_Main(0, (LPTSTR*)NULL);
     return(0);
 }
 
index c2e6f3e..fe3fa42 100644 (file)
 
 /* from .xg file */
 /* FIXME: these were "long" but Windows NT wants "int" */
-int VL_GetEntryByID(struct rx_connection *, long, long, struct vldbentry *);
+int VL_GetEntryByID(struct rx_connection *, afs_int32, afs_int32, struct vldbentry *);
 int VL_GetEntryByNameO(struct rx_connection *, char *, struct vldbentry *);
 int VL_ProbeServer(struct rx_connection *);
-int VL_GetEntryBYIDN(struct rx_connection *, long, long, struct nvldbentry *);
+int VL_GetEntryBYIDN(struct rx_connection *, afs_int32, afs_int32, struct nvldbentry *);
 int VL_GetEntryByNameN(struct rx_connection *, char *, struct nvldbentry *);
 
 /* from .xg file */
@@ -49,9 +49,9 @@ extern RXAFS_FetchStatus (struct rx_connection *,
 int StartRXAFS_StoreData (struct rx_call *,
        struct AFSFid *Fid, 
        struct AFSStoreStatus *InStatus, 
-       afs_int32 Pos, 
-       afs_int32 Length, 
-       afs_int32 FileLength);
+       afs_uint32 Pos, 
+       afs_uint32 Length, 
+       afs_uint32 FileLength);
 
 int EndRXAFS_StoreData(struct rx_call *,
        struct AFSFetchStatus *OutStatus, 
index 8752cb2..d8ca53e 100644 (file)
@@ -86,6 +86,8 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, long flags)
         memset(cp, 0, sizeof(*cp));
         code = cm_SearchCellFile(namep, fullname, cm_AddCellProc, cp);
                if (code) {
+            afsi_log("in cm_GetCell_gen code= %d fullname= %s", code, fullname);
+
 #ifdef AFS_AFSDB_ENV
             if (cm_dnsEnabled /*&& cm_DomainValid(namep)*/)
                 code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, cp);
index 37ed889..60105fc 100644 (file)
 
 #include "cm_config.h"
 #ifdef AFS_AFSDB_ENV
+#if !defined(DJGPP) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x500
+#include <windns.h>
+#define DNSAPI_ENV
+#else
 #include "cm_dns.h"
+#endif
 #include <afs/afsint.h>
 #endif
 
 char AFSConfigKeyName[] =
        "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
 
+/* TODO: these should be pulled in from dirpath.h */
 #define AFS_THISCELL "ThisCell"
 #define AFS_CELLSERVDB_UNIX "CellServDB"
 #define AFS_CELLSERVDB_NT "afsdcell.ini"
@@ -46,6 +52,38 @@ extern int errno;
 #define AFS_CELLSERVDB AFS_CELLSERVDB_NT
 #endif /* DJGPP || WIN95 */
 
+DWORD TraceOption=1;
+
+#define TRACE_OPTION_EVENT 1
+#define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
+
+void DebugEvent0_local(char *a) 
+{
+       HANDLE h; char *ptbuf[1];
+       if (!ISLOGONTRACE(TraceOption))
+               return;
+       h = RegisterEventSource(NULL, a);
+       ptbuf[0] = a;
+       ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
+       DeregisterEventSource(h);
+}
+
+#define MAXBUF_ 131
+
+void DebugEvent_local(char *a,char *b,...) 
+{
+       HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
+       va_list marker;
+       if (!ISLOGONTRACE(TraceOption))
+               return;
+       h = RegisterEventSource(NULL, a);
+       va_start(marker,b);
+       _vsnprintf(buf,MAXBUF_,b,marker);
+       ptbuf[0] = buf;
+       ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
+       DeregisterEventSource(h);
+       va_end(marker);
+}
 
 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
 {
@@ -128,8 +166,8 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
        long ip_addr;
     int c1, c2, c3, c4;
     char aname[256];
-#endif
     char *afsconf_path;
+#endif
 
        foundCell = 0;
 
@@ -150,6 +188,7 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
 
     tfilep = fopen(wdir, "r");
 
+#if defined(DJGPP) || defined(AFS_WIN95_ENV)
     if (!tfilep) {
         /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
         /* If we are in Win95 here, we are linking with klog etc. and are
@@ -166,9 +205,16 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
         tfilep = fopen(wdir, "r");
         if (!tfilep) return -2;
     }
+#else
+    /* If we are NT or higher, we don't do DJGPP, So just fail */
+    if ( !tfilep )
+        return -2;
+#endif
 
        bestp = fopen(wdir, "r");
-        
+    
+    DebugEvent_local("AFS- cm_searchfile fopen", "Handle[%x], wdir[%s]", bestp, wdir);
+
        /* have we seen the cell line for the guy we're looking for? */
        inRightCell = 0;
        while (1) {
@@ -223,6 +269,8 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                                        strcpy(newCellNamep, lineBuffer+1);
                 inRightCell = 1;
                                tracking = 0;
+                DebugEvent_local("AFS- cm_searchfile is cell", "inRightCell[%x], linebuffer[%s]", 
+                                 inRightCell, lineBuffer);
                        }
                        else if (strnicmp(lineBuffer+1, cellNamep,
                                strlen(cellNamep)) == 0) {
@@ -260,7 +308,15 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                        if (inRightCell) {
 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
                                /* add the server to the VLDB list */
+                WSASetLastError(0);
                 thp = gethostbyname(valuep);
+                {
+                    int iErr = 0;
+                    iErr = WSAGetLastError();
+                    DebugEvent_local("AFS- cm_searchfile inRightCell", 
+                                     "thp[%x], valuep[%s], WSAGetLastError[%d]", 
+                                     thp, valuep, iErr);
+                }
                 if (thp) {
                                        memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
                             sizeof(long));
@@ -300,29 +356,121 @@ long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
                cm_configProc_t *procp, void *rockp)
 {
 #ifdef AFS_AFSDB_ENV
-     int rc;
-     int cellHosts[AFSMAXCELLHOSTS];
-     int numServers;
-     int i;
-     struct sockaddr_in vlSockAddr;
-
-     rc = getAFSServer(cellNamep, cellHosts, &numServers, ttl);
-     if (rc == 0 && numServers > 0) {     /* found the cell */
-       for (i = 0; i < numServers; i++) {
-           memcpy(&vlSockAddr.sin_addr.s_addr, &cellHosts[i],
-               sizeof(long));
+#ifndef DNSAPI_ENV
+    int rc;
+    int cellHosts[AFSMAXCELLHOSTS];
+    int numServers;
+    int i;
+    struct sockaddr_in vlSockAddr;
+
+    DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
+    rc = getAFSServer(cellNamep, cellHosts, &numServers, ttl);
+    if (rc == 0 && numServers > 0) {     /* found the cell */
+        for (i = 0; i < numServers; i++) {
+            memcpy(&vlSockAddr.sin_addr.s_addr, &cellHosts[i],
+                   sizeof(long));
            vlSockAddr.sin_family = AF_INET;
            /* sin_port supplied by connection code */
            if (procp)
           (*procp)(rockp, &vlSockAddr, NULL);
            if(newCellNamep)
           strcpy(newCellNamep,cellNamep);
-       }
-       return 0;   /* found cell */
-     }
-     else
-#endif /* AFS_AFSDB_ENV */
+        }
+        return 0;   /* found cell */
+    }
+    else
        return -1;  /* not found */
+#else /* DNSAPI_ENV */
+       PDNS_RECORD pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
+       LPSTR vlServers[AFSMAXCELLHOSTS];
+       IP4_ADDRESS vlAddrs[AFSMAXCELLHOSTS];
+       WORD nvlServers;
+       DWORD wttl, i;
+       BOOL success;
+    struct sockaddr_in vlSockAddr;
+
+       success = FALSE;
+
+       /* query the AFSDB records of cell */
+       if(DnsQuery_A(cellNamep, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
+
+               memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));
+               
+               nvlServers = 0; wttl = 0;
+
+               /* go through the returned records */
+               for(pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
+                       /* if we find an AFSDB record with Preference set to 1, we found a volserver */
+                       if(pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
+                               vlServers[nvlServers++] = pDnsIter->Data.Afsdb.pNameExchange;
+                               if(!wttl) wttl = pDnsIter->dwTtl;
+                               if(nvlServers == AFSMAXCELLHOSTS) break;
+                       }
+               }
+
+               for(i=0;i<nvlServers;i++) vlAddrs[i] = 0;
+
+               /* now check if there are any A records in the results */
+               for(pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
+                       if(pDnsIter->wType == DNS_TYPE_A)
+                               /* check if its for one of the volservers */
+                               for(i=0;i<nvlServers;i++)
+                                       if(stricmp(pDnsIter->pName, vlServers[i]) == 0)
+                                               vlAddrs[i] = pDnsIter->Data.A.IpAddress;
+               }
+
+               for(i=0;i<nvlServers;i++) {
+                       /* if we don't have an IP yet, then we should try resolving the volserver hostname
+                          in a separate query. */
+                       if(!vlAddrs[i]) {
+                               if(DnsQuery_A(vlServers[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
+                                       for(pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
+                                               /* if we get an A record, keep it */
+                                               if(pDnsVolIter->wType == DNS_TYPE_A && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
+                                                       vlAddrs[i] = pDnsVolIter->Data.A.IpAddress;
+                                                       break;
+                                               }
+                                               /* if we get a CNAME, look for a corresponding A record */
+                                               if(pDnsVolIter->wType == DNS_TYPE_CNAME && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
+                                                       for(pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
+                                                               if(pDnsCIter->wType == DNS_TYPE_A && stricmp(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
+                                                                       vlAddrs[i] = pDnsCIter->Data.A.IpAddress;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       if(vlAddrs[i]) break;
+                                                       /* TODO: if the additional section is missing, then do another lookup for the CNAME */
+                                               }
+                                       }
+                                       /* we are done with the volserver lookup */
+                                       DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
+                               }
+                       }
+
+                       /* if we found a volserver, then add it */
+                       if(vlAddrs[i]) {
+                               vlSockAddr.sin_family = AF_INET;
+                               vlSockAddr.sin_addr.s_addr = vlAddrs[i];
+                               if(procp)
+                                       (*procp)(rockp, &vlSockAddr, vlServers[i]);
+                               success = TRUE;
+                       }
+               }
+
+               DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
+       }
+
+       if(!success) return -1;
+       else {
+               strcpy(newCellNamep, cellNamep);
+               if(ttl) *ttl = (int) wttl;
+               return 0;
+       }
+
+#endif /* DNSAPI_ENV */
+#else
+       return -1;  /* not found */
+#endif /* AFS_AFSDB_ENV */
 }
 
 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
index 97f6b38..7d001e3 100644 (file)
@@ -137,6 +137,7 @@ long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp,
  *
  * volSyncp and/or cbrp may also be NULL.
  */
+int
 cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
        struct cm_fid *fidp,
        AFSVolSync *volSyncp, cm_callbackRequest_t *cbrp, long errorCode)
index 98d2668..4bf8e8e 100644 (file)
@@ -1272,140 +1272,140 @@ long cm_NameI(cm_scache_t *rootSCachep, char *pathp, long flags,
         cm_HoldSCache(tscp);
         symlinkCount = 0;
         while (1) {
-               tc = *tp++;
+            tc = *tp++;
                
-                /* map Unix slashes into DOS ones so we can interpret Unix
-                * symlinks properly
-                 */
-                if (tc == '/') tc = '\\';
-               
-                if (!haveComponent) {
+            /* map Unix slashes into DOS ones so we can interpret Unix
+             * symlinks properly
+             */
+            if (tc == '/') tc = '\\';
+
+            if (!haveComponent) {
                        if (tc == '\\') continue;
-                        else if (tc == 0) {
+            else if (tc == 0) {
                                if (phase == 1) {
                                        phase = 2;
                                        tp = pathp;
                                        continue;
                                }
-                               code = 0;
-                                break;
-                        }
-                        else {
+                code = 0;
+                break;
+            }
+            else {
                                haveComponent = 1;
-                                cp = component;
-                                *cp++ = tc;
+                cp = component;
+                *cp++ = tc;
+            }
+            }
+            else {
+                /* we have a component here */
+                if (tc == 0 || tc == '\\') {
+                    /* end of the component; we're at the last
+                     * component if tc == 0.  However, if the last
+                     * is a symlink, we have more to do.
+                     */
+                    *cp++ = 0; /* add null termination */
+                    extraFlag = 0;
+                    if ((flags & CM_FLAG_DIRSEARCH) && tc == 0)
+                        extraFlag = CM_FLAG_NOMOUNTCHASE;
+                    code = cm_Lookup(tscp, component,
+                                      flags | extraFlag,
+                                      userp, reqp, &nscp);
+
+                    if (code) {
+                        cm_ReleaseSCache(tscp);
+                        if (psp) cm_FreeSpace(psp);
+                        return code;
+                    }
+                    haveComponent = 0; /* component done */
+                    dirScp = tscp;             /* for some symlinks */
+                    tscp = nscp;       /* already held */
+                    if (tc == 0 && !(flags & CM_FLAG_FOLLOW) && phase == 2) {
+                        code = 0;
+                        cm_ReleaseSCache(dirScp);
+                        break;
+                    }
+
+                    /* now, if tscp is a symlink, we should follow
+                     * it and assemble the path again.
+                     */
+                    lock_ObtainMutex(&tscp->mx);
+                    code = cm_SyncOp(tscp, NULL, userp, reqp, 0,
+                                      CM_SCACHESYNC_GETSTATUS
+                                      | CM_SCACHESYNC_NEEDCALLBACK);
+                    if (code) {
+                        lock_ReleaseMutex(&tscp->mx);
+                        cm_ReleaseSCache(tscp);
+                        cm_ReleaseSCache(dirScp);
+                        break;
+                    }
+                    if (tscp->fileType == CM_SCACHETYPE_SYMLINK) {
+                        /* this is a symlink; assemble a new buffer */
+                        lock_ReleaseMutex(&tscp->mx);
+                        if (symlinkCount++ >= 16) {
+                            cm_ReleaseSCache(tscp);
+                            cm_ReleaseSCache(dirScp);
+                            if (psp) cm_FreeSpace(psp);
+                            return CM_ERROR_TOOBIG;
                         }
-                }
-               else {
-                       /* we have a component here */
-                        if (tc == 0 || tc == '\\') {
-                               /* end of the component; we're at the last
-                                * component if tc == 0.  However, if the last
-                                * is a symlink, we have more to do.
-                                 */
-                                *cp++ = 0;     /* add null termination */
-                               extraFlag = 0;
-                               if ((flags & CM_FLAG_DIRSEARCH) && tc == 0)
-                                       extraFlag = CM_FLAG_NOMOUNTCHASE;
-                                code = cm_Lookup(tscp, component,
-                                       flags | extraFlag,
-                                       userp, reqp, &nscp);
-                                if (code) {
-                                       cm_ReleaseSCache(tscp);
-                                        if (psp) cm_FreeSpace(psp);
-                                        return code;
-                                }
-                                haveComponent = 0;     /* component done */
-                                dirScp = tscp;         /* for some symlinks */
-                                tscp = nscp;   /* already held */
-                                if (tc == 0 && !(flags & CM_FLAG_FOLLOW) && phase == 2) {
-                                       code = 0;
-                                        cm_ReleaseSCache(dirScp);
-                                       break;
-                               }
-                                
-                                /* now, if tscp is a symlink, we should follow
-                                * it and assemble the path again.
-                                 */
-                               lock_ObtainMutex(&tscp->mx);
-                               code = cm_SyncOp(tscp, NULL, userp, reqp, 0,
-                                       CM_SCACHESYNC_GETSTATUS
-                                        | CM_SCACHESYNC_NEEDCALLBACK);
-                                if (code) {
-                                       lock_ReleaseMutex(&tscp->mx);
-                                       cm_ReleaseSCache(tscp);
-                                        cm_ReleaseSCache(dirScp);
-                                        break;
-                                }
-                                if (tscp->fileType == CM_SCACHETYPE_SYMLINK) {
-                                       /* this is a symlink; assemble a new buffer */
-                                       lock_ReleaseMutex(&tscp->mx);
-                                        if (symlinkCount++ >= 16) {
-                                               cm_ReleaseSCache(tscp);
-                                                cm_ReleaseSCache(dirScp);
-                                               if (psp) cm_FreeSpace(psp);
-                                                return CM_ERROR_TOOBIG;
-                                        }
-                                        if (tc == 0) restp = "";
-                                        else restp = tp;
-                                        code = cm_AssembleLink(tscp, restp,
-                                               &linkScp, &tempsp, userp, reqp);
-                                        if (code) {
-                                               /* something went wrong */
-                                               cm_ReleaseSCache(tscp);
-                                                cm_ReleaseSCache(dirScp);
-                                               break;
-                                        }
-                                        
-                                        /* otherwise, tempsp has the new path,
-                                        * and linkScp is the new root from
-                                        * which to interpret that path.
-                                        * Continue with the namei processing,
-                                        * also doing the bookkeeping for the
-                                        * space allocation and tracking the
-                                         * vnode reference counts.
-                                         */
-                                       if (psp) cm_FreeSpace(psp);
-                                       psp = tempsp;
-                                        tp = psp->data;
-                                        cm_ReleaseSCache(tscp);
-                                        tscp = linkScp;        /* already held
-                                                        * by AssembleLink */
-                                        /* now, if linkScp is null, that's
-                                        * AssembleLink's way of telling us that
-                                        * the sym link is relative to the dir
-                                        * containing the link.  We have a ref
-                                        * to it in dirScp, and we hold it now
-                                        * and reuse it as the new spot in the
-                                        * dir hierarchy.
-                                         */
-                                        if (tscp == NULL) {
-                                               cm_HoldSCache(dirScp);
-                                                tscp = dirScp;
-                                        }
-                                }      /* if we have a sym link */
-                                else {
-                                       /* not a symlink, we may be done */
-                                       lock_ReleaseMutex(&tscp->mx);
-                                        if (tc == 0) {
-                                               if (phase == 1) {
-                                                       phase = 2;
-                                                       tp = pathp;
-                                                       continue;
-                                               }
-                                               cm_ReleaseSCache(dirScp);
-                                                code = 0;
-                                                break;
-                                        }
-                               }
-                                cm_ReleaseSCache(dirScp);
-                        } /* end of a component */
-                        else *cp++ = tc;
-                } /* we have a component */
-        }      /* big while loop over all components */
+                        if (tc == 0) restp = "";
+                        else restp = tp;
+                        code = cm_AssembleLink(tscp, restp, &linkScp, &tempsp, userp, reqp);
+                        if (code) {
+                            /* something went wrong */
+                            cm_ReleaseSCache(tscp);
+                            cm_ReleaseSCache(dirScp);
+                            break;
+                        }
+
+                        /* otherwise, tempsp has the new path,
+                         * and linkScp is the new root from
+                         * which to interpret that path.
+                         * Continue with the namei processing,
+                         * also doing the bookkeeping for the
+                         * space allocation and tracking the
+                         * vnode reference counts.
+                         */
+                        if (psp) cm_FreeSpace(psp);
+                        psp = tempsp;
+                        tp = psp->data;
+                        cm_ReleaseSCache(tscp);
+                        tscp = linkScp;        /* already held
+                                         * by AssembleLink */
+                        /* now, if linkScp is null, that's
+                         * AssembleLink's way of telling us that
+                         * the sym link is relative to the dir
+                         * containing the link.  We have a ref
+                         * to it in dirScp, and we hold it now
+                         * and reuse it as the new spot in the
+                         * dir hierarchy.
+                         */
+                        if (tscp == NULL) {
+                            cm_HoldSCache(dirScp);
+                            tscp = dirScp;
+                        }
+                    }  /* if we have a sym link */
+                    else {
+                        /* not a symlink, we may be done */
+                        lock_ReleaseMutex(&tscp->mx);
+                        if (tc == 0) {
+                            if (phase == 1) {
+                                phase = 2;
+                                tp = pathp;
+                                continue;
+                            }
+                            cm_ReleaseSCache(dirScp);
+                            code = 0;
+                            break;
+                        }
+                    }
+                    cm_ReleaseSCache(dirScp);
+                } /* end of a component */
+                else *cp++ = tc;
+            } /* we have a component */
+        } /* big while loop over all components */
 
        /* already held */
-        if (psp) cm_FreeSpace(psp);
+    if (psp) cm_FreeSpace(psp);
        if (code == 0) *outScpp = tscp;
         return code;
 }
index 4979eaf..064f1f9 100644 (file)
@@ -130,12 +130,12 @@ struct hostent *hostutil_GetHostByName(char *namep)
 }
 
 /* get hostname or addr, given addr in network byte order */
-char *hostutil_GetNameByINet(long addr)
+char *hostutil_GetNameByINet(afs_uint32 addr)
 {
        static char hostNameBuffer[256];
         struct hostent *thp;
         
-        thp = gethostbyaddr((char *) &addr, sizeof(long), AF_INET);
+        thp = gethostbyaddr((char *) &addr, sizeof(afs_uint32), AF_INET);
         if (thp)
                strcpy(hostNameBuffer, thp->h_name);
        else {
index cdac4fc..dabe1ae 100644 (file)
@@ -25,7 +25,9 @@
 /* Fake error code since NT errno.h doesn't define it */
 #include <afs/errmap_nt.h>
 
-//extern char *hostutil_GetNameByINet(long addr);
+#ifndef hostutil_GetNameByINet
+extern char *hostutil_GetNameByINet(afs_uint32 addr);
+#endif
 
 #ifndef hostutil_GetHostByName
 extern struct hostent *hostutil_GetHostByName(char *namep);
diff --git a/src/WINNT/afsd/lanahelper.cpp b/src/WINNT/afsd/lanahelper.cpp
new file mode 100644 (file)
index 0000000..eaeb323
--- /dev/null
@@ -0,0 +1,318 @@
+#include <afx.h>
+#include <windows.h>
+#include <winreg.h>
+#include <nb30.h>
+#include <tchar.h>
+#include <shellapi.h>
+#include <objbase.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <wtypes.h>
+#include <string.h>
+#include <malloc.h>
+#include "lanahelper.h"
+
+
+extern "C" void afsi_log(...);
+
+static HRESULT getname_shellfolder(WCHAR *wGuid, WCHAR *wName, int NameSize)
+{
+    // This is the GUID for the network connections folder. It is constant.
+    // {7007ACC7-3202-11D1-AAD2-00805FC1270E}
+    const GUID CLSID_NetworkConnections = {
+        0x7007ACC7, 0x3202, 0x11D1, {
+           0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
+       }
+    };
+    LPITEMIDLIST pidl;
+    IShellFolder *pShellFolder;
+    IMalloc *pShellMalloc;
+
+    // Build the display name in the form "::{GUID}".
+    if (wcslen(wGuid) >= MAX_PATH)
+        return E_INVALIDARG;
+    WCHAR szAdapterGuid[MAX_PATH + 2];
+    swprintf(szAdapterGuid, L"::%ls", wGuid);
+
+    // Initialize COM.
+    CoInitialize(NULL);
+
+    // Get the shell allocator.
+    HRESULT hr = SHGetMalloc(&pShellMalloc);
+    if (SUCCEEDED(hr))
+        // Create an instance of the network connections folder.
+        hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
+                             CLSCTX_INPROC_SERVER, IID_IShellFolder,
+                             reinterpret_cast<LPVOID *>(&pShellFolder));
+    if (SUCCEEDED(hr))
+        hr = pShellFolder->ParseDisplayName(NULL, NULL, szAdapterGuid, NULL,
+                                           &pidl, NULL);
+    if (SUCCEEDED(hr)) {
+        // Get the display name; this returns the friendly name.
+        STRRET sName;
+       hr = pShellFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL, &sName);
+       if (SUCCEEDED(hr))
+            wcsncpy(wName, sName.pOleStr, NameSize);
+       pShellMalloc->Free(pidl);
+    }
+
+    CoUninitialize();
+    return hr;
+}
+
+// Get the Connection Name for the given GUID.
+extern "C" int lana_GetNameFromGuid(char *Guid, char **Name)
+{
+    typedef HRESULT (WINAPI *HrLanProcAddr)(GUID *, PCWSTR, PWSTR, LPDWORD);
+    HrLanProcAddr HrLanProc = NULL;
+    HMODULE hNetMan;
+    int size;
+    WCHAR *wGuid = NULL;
+    WCHAR wName[MAX_PATH];
+    DWORD NameSize = (sizeof(wName) / sizeof(wName[0]));
+    HRESULT status;
+        
+    // Convert the Guid string to Unicode.  First we ask only for the size
+    // of the converted string.  Then we allocate a buffer of sufficient
+    // size to hold the result of the conversion.
+    size = MultiByteToWideChar(CP_ACP, 0, Guid, -1, NULL, 0);
+    wGuid = (WCHAR *) malloc(size * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, Guid, -1, wGuid, size);
+
+    // First try the IShellFolder interface, which was unimplemented
+    // for the network connections folder before XP.
+
+    /* XXX pbh 9/11/03 - revert to using the undocumented APIs on XP while
+     *   waiting tohear back from PSS about the slow reboot issue.
+     *   This is an ungly, misleading hack, but is minimally invasive
+     *   and will be easy to rollback.
+     */
+
+    //status = getname_shellfolder(wGuid, wName, NameSize);
+      status = E_NOTIMPL;
+
+    /* XXX end of pbh 9/11/03 temporary hack*/ 
+
+    if (status == E_NOTIMPL) {
+       // The IShellFolder interface is not implemented on this platform.
+       // Try the (undocumented) HrLanConnectionNameFromGuidOrPath API
+       // from the netman DLL.
+       afsi_log("IShellFolder API not implemented, trying HrLanConnectionNameFromGuidOrPath");
+        hNetMan = LoadLibrary("netman.dll");
+       if (hNetMan == NULL) {
+           free(wGuid);
+            return -1;
+       }
+       HrLanProc =
+          (HrLanProcAddr) GetProcAddress(hNetMan,
+                                        "HrLanConnectionNameFromGuidOrPath");
+       if (HrLanProc == NULL) {
+            FreeLibrary(hNetMan);
+           free(wGuid);
+            return -1;
+       }
+       status = HrLanProc(NULL, wGuid, wName, &NameSize);
+       FreeLibrary(hNetMan);
+    }
+    free(wGuid);
+    if (FAILED(status)) {
+        afsi_log("lana_GetNameFromGuid: failed to get connection name (status %ld)",
+                status);
+       return -1;
+    }
+
+    // Get the required buffer size, and then convert the string.
+    size = WideCharToMultiByte(CP_ACP, 0, wName, -1, NULL, 0, NULL, NULL);
+    *Name = (char *) malloc(size);
+    if (*Name == NULL)
+        return -1;
+    WideCharToMultiByte(CP_ACP, 0, wName, -1, *Name, size, NULL, NULL);
+    afsi_log("Connection name for %s is '%s'", Guid, *Name);
+    return 0;
+}
+
+// Find the lana number for the given connection name.
+extern "C" lana_number_t lana_FindLanaByName(const char *LanaName)
+{
+    const char RegNetBiosLinkageKeyName[] =
+        "System\\CurrentControlSet\\Services\\NetBios\\Linkage";
+    HKEY hkey;
+    LONG status;
+    struct {
+        BYTE flags;
+        BYTE number;
+    } lanamap[MAX_LANA+1];
+    DWORD lanamapsize = sizeof(lanamap);
+    DWORD type;
+    char *bindpaths = NULL;
+    DWORD bindpathsize;
+    int nlana;
+    int i;
+    char *guid;
+    char *name;
+    char *pBind;
+    char *p;
+
+    // Open the NetBios Linkage key.
+    status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegNetBiosLinkageKeyName, 0, 
+                          KEY_QUERY_VALUE, &hkey);
+        
+    if (status != ERROR_SUCCESS) { 
+        afsi_log("Failed to open NetBios Linkage key (status %ld)", status);
+        return LANA_INVALID;
+    }
+
+    // Read the lana map.
+    status = RegQueryValueEx(hkey, "LanaMap", 0, &type,
+                         (BYTE *) &lanamap, &lanamapsize);
+    if (status != ERROR_SUCCESS) {
+        afsi_log("Failed to read LanaMap (status %ld)", status);
+        RegCloseKey(hkey);
+        return LANA_INVALID;
+    }
+    if (lanamapsize == 0) {
+        afsi_log("No data in LanaMap");
+        return LANA_INVALID;
+    }
+    nlana = lanamapsize / sizeof(lanamap[0]);
+
+    // Get the bind paths for NetBios so we can match them up
+    // with the lana map.  First we query for the size, so we
+    // can allocate an appropriate buffer.
+    status = RegQueryValueEx(hkey, "Bind", 0, &type, NULL, &bindpathsize);
+    if (status == ERROR_SUCCESS && bindpathsize != 0) {
+        bindpaths = (char *) malloc(bindpathsize * sizeof(char));
+        if (bindpaths == NULL) {
+            afsi_log("Cannot allocate %ld bytes for bindpaths", bindpathsize);
+            RegCloseKey(hkey);
+            return LANA_INVALID;
+        }
+        status = RegQueryValueEx(hkey, "Bind", 0, &type, 
+                                 (BYTE *) bindpaths, &bindpathsize);
+    }
+    RegCloseKey(hkey);
+    if (status != ERROR_SUCCESS) {
+        afsi_log("Failed to read bind paths (status %ld)", status);
+        if (bindpaths != NULL)
+            free(bindpaths);
+        return LANA_INVALID;
+      }
+    if (bindpathsize == 0) {
+        afsi_log("No bindpath data");
+        if (bindpaths != NULL)
+            free(bindpaths);
+        return LANA_INVALID;
+    }
+
+    // Iterate over the lana map entries and bind paths.
+    for (i = 0, pBind = bindpaths; i < nlana;
+         i++, pBind += strlen(pBind) + 1) {
+       // Ignore an invalid map entry.
+        if ((lanamap[i].flags & 1) == 0)
+            continue;
+
+               // check for a IPv4 binding
+               if(!strstr(pBind,"_Tcpip_"))
+                       continue;
+
+        // Find the beginning of the GUID.
+        guid = strchr(pBind, '{');
+        if (guid == NULL)
+           continue;                   // Malformed path entry?
+        guid = strdup(guid);
+        if (guid == NULL)
+            continue;
+       // Find the end of the GUID.
+        p = strchr(guid, '}');
+        if (p == NULL) {
+           free(guid);                 // Malformed GUID?
+            continue;
+        }
+        *++p = '\0';                    // Ignore anything after the GUID.
+        status = lana_GetNameFromGuid(guid, &name);
+        free(guid);
+        if (status == 0) {
+            status = strcmp(name, LanaName);
+            free(name);
+            if (status == 0) {
+                free(bindpaths);
+               afsi_log("lana_FindLanaByName: Found lana %d for %s",
+                        lanamap[i].number, LanaName);
+               return lanamap[i].number;
+           }
+       }
+    }
+    free(bindpaths);
+    return LANA_INVALID;
+}
+
+extern "C" lana_number_t lana_FindLoopback(void)
+{
+    NCB ncb;
+    LANA_ENUM lana_list;
+    int status;
+    int i;
+
+    memset(&ncb, 0, sizeof(ncb));
+    ncb.ncb_command = NCBENUM;
+    ncb.ncb_buffer = (UCHAR *) &lana_list;
+    ncb.ncb_length = sizeof(lana_list);
+    status = Netbios(&ncb);
+    if (status != 0) {
+       afsi_log("Netbios NCBENUM failed: status %ld", status);
+       return LANA_INVALID;
+    }
+    for (i = 0; i < lana_list.length; i++) {
+       if (lana_IsLoopback(lana_list.lana[i])) {
+           // Found one, return it.
+           afsi_log("lana_FindLoopback: Found LAN adapter %d",
+                    lana_list.lana[i]);
+           return lana_list.lana[i];
+       }
+    }
+    // Could not find a loopback adapter.
+    return LANA_INVALID;
+}
+
+// Is the given lana a Windows Loopback Adapter?
+extern "C" BOOL lana_IsLoopback(lana_number_t lana)
+{
+    NCB ncb;
+    struct {
+        ADAPTER_STATUS status;
+        NAME_BUFFER names[MAX_LANA+1];
+    } astat;
+    unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
+    int status;
+
+    // Reset the adapter: in Win32, this is required for every process, and
+    // acts as an init call, not as a real hardware reset.
+    memset(&ncb, 0, sizeof(ncb));
+    ncb.ncb_command = NCBRESET;
+    ncb.ncb_callname[0] = 100;
+    ncb.ncb_callname[2] = 100;
+    ncb.ncb_lana_num = lana;
+    status = Netbios(&ncb);
+    if (status == 0)
+        status = ncb.ncb_retcode;
+    if (status != 0) {
+       afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
+       return FALSE;
+    }
+
+    // Use the NCBASTAT command to get the adapter address.
+    memset(&ncb, 0, sizeof(ncb));
+    ncb.ncb_command = NCBASTAT;
+    ncb.ncb_lana_num = lana;
+    strcpy((char *) ncb.ncb_callname, "*               ");
+    ncb.ncb_buffer = (UCHAR *) &astat;
+    ncb.ncb_length = sizeof(astat);
+    status = Netbios(&ncb);
+    if (status == 0)
+        status = ncb.ncb_retcode;
+    if (ncb.ncb_retcode != 0) {
+        afsi_log("NCBASTAT failed: lana %u, status %ld", lana, status);
+       return FALSE;
+    }
+    return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);
+}
diff --git a/src/WINNT/afsd/lanahelper.h b/src/WINNT/afsd/lanahelper.h
new file mode 100644 (file)
index 0000000..4526464
--- /dev/null
@@ -0,0 +1,21 @@
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  typedef BYTE lana_number_t;
+
+#define LANA_INVALID 0xff
+
+  int lana_GetNameFromGuid(char *Guid, char **Name);
+
+  lana_number_t lana_FindLanaByName(const char *LanaName);
+
+  lana_number_t lana_FindLoopback(void);
+
+  BOOL lana_IsLoopback(lana_number_t lana);
+
+#ifdef __cplusplus
+}
+#endif
index 0be9cff..ecb2ab4 100644 (file)
@@ -32,6 +32,7 @@
 #include "afsd.h"
 
 #include "smb.h"
+#include "lanahelper.h"
 
 /* These characters are illegal in Windows filenames */
 static char *illegalChars = "\\/:*?\"<>|";
@@ -40,6 +41,7 @@ BOOL isWindows2000 = FALSE;
 smb_vc_t *dead_vcp = NULL;
 smb_vc_t *active_vcp = NULL;
 
+/* TODO; logout mechanism needs to be thread-safe */
 char *loggedOutName = NULL;
 smb_user_t *loggedOutUserp = NULL;
 unsigned long loggedOutTime;
@@ -83,6 +85,9 @@ int smb_NumServerThreads;
 
 int numNCBs, numSessions;
 
+int smb_maxVCPerServer;
+int smb_maxMpxRequests;
+
 #define NCBmax 100
 EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
 EVENT_HANDLE **NCBreturns;
@@ -128,6 +133,9 @@ long smb_dirSearchCounter = 1;
 smb_dirSearch_t *smb_firstDirSearchp;
 smb_dirSearch_t *smb_lastDirSearchp;
 
+/* hide dot files? */
+int smb_hideDotFiles;
+
 /* global state about V3 protocols */
 int smb_useV3;         /* try to negotiate V3 */
 
@@ -145,7 +153,7 @@ long smb_localZero;
 /* Time difference for converting to kludge-GMT */
 int smb_NowTZ;
 
-char *smb_localNamep;
+char *smb_localNamep = NULL;
 
 smb_vc_t *smb_allVCsp;
 
@@ -158,6 +166,10 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        NCB *ncbp, raw_write_cont_t *rwcp);
 void smb_NetbiosInit();
 #ifdef DJGPP
+#ifndef AFS_WIN95_ENV
+DWORD smb_ServerExceptionFilter(void);
+#endif
+
 extern char cm_HostName[];
 extern char cm_confDir[];
 #endif
@@ -326,7 +338,7 @@ unsigned int smb_Attributes(cm_scache_t *scp)
 
        if (scp->fileType == CM_SCACHETYPE_DIRECTORY
                || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-                       attrs = 0x10;
+                       attrs = SMB_ATTR_DIRECTORY;
        else
                attrs = 0;
 
@@ -338,11 +350,33 @@ unsigned int smb_Attributes(cm_scache_t *scp)
        if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
 #endif
        if ((scp->unixModeBits & 0222) == 0)
-               attrs |= 1;     /* turn on read-only flag */
+               attrs |= SMB_ATTR_READONLY;     /* turn on read-only flag */
 
        return attrs;
 }
 
+/* Check if the named file/dir is a dotfile/dotdir */
+/* String pointed to by lastComp can have leading slashes, but otherwise should have
+   no other patch components */
+unsigned int smb_IsDotFile(char *lastComp) {
+       char *s;
+       if(lastComp) {
+               /* skip over slashes */
+        for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
+       }
+       else
+               return 0;
+
+    /* nulls, curdir and parent dir doesn't count */
+       if(!*s) return 0;
+       if(*s == '.') {
+               if(!*(s + 1)) return 0;
+               if(*(s+1) == '.' && !*(s + 2)) return 0;
+               return 1;
+       }
+       return 0;
+}
+
 static int ExtractBits(WORD bits, short start, short len)
 {
         int end;
@@ -814,6 +848,7 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
         if (!unp && (flags & SMB_FLAG_CREATE)) {
           unp = malloc(sizeof(*unp));
           memset(unp, 0, sizeof(*unp));
+          unp->refCount = 1;
           unp->nextp = usernamesp;
           unp->name = strdup(usern);
           unp->machine = strdup(machine);
@@ -904,6 +939,8 @@ char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid)
        char *tpath;
 
        tidp = smb_FindTID(vcp, tid, 0);
+    if (!tidp) 
+        return NULL;
        tpath = tidp->pathname;
        smb_ReleaseTID(tidp);
        return tpath;
@@ -977,6 +1014,9 @@ void smb_ReleaseFID(smb_fid_t *fidp)
         smb_vc_t *vcp;
         smb_ioctl_t *ioctlp;
 
+    if (!fidp)
+        return NULL;
+
        scp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(fidp->refCount-- > 0);
@@ -1159,7 +1199,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
                        else
                          smb_subst(p, var, sizeof(VNUserName),
                                       " ");
-                       smb_ReleaseUID(uidp);
+                       if (uidp)
+                smb_ReleaseUID(uidp);
                }
                else if (var = smb_stristr(p, VNLCUserName)) {
                        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
@@ -1168,7 +1209,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
                        else strcpy(temp, " ");
                        _strlwr(temp);
                        smb_subst(p, var, sizeof(VNLCUserName), temp);
-                       smb_ReleaseUID(uidp);
+                       if (uidp)
+                smb_ReleaseUID(uidp);
                }
                else if (var = smb_stristr(p, VNComputerName)) {
                        sizeTemp = sizeof(temp);
@@ -1370,7 +1412,8 @@ static smb_packet_t *GetPacket(void)
 
        lock_ObtainWrite(&smb_globalLock);
        tbp = smb_packetFreeListp;
-        if (tbp) smb_packetFreeListp = tbp->nextp;
+    if (tbp) 
+        smb_packetFreeListp = tbp->nextp;
        lock_ReleaseWrite(&smb_globalLock);
     if (!tbp) {
 #ifndef DJGPP
@@ -1389,6 +1432,7 @@ static smb_packet_t *GetPacket(void)
                tbp->oddByte = 0;
                tbp->ncb_length = 0;
                tbp->flags = 0;
+        tbp->spacep = NULL;
         
 #ifdef DJGPP
         npar = SMB_PACKETSIZE >> 4;  /* number of paragraphs */
@@ -2275,12 +2319,12 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
                /* compute size of protocol entry */
                entryLength = strlen(namep+1);
-                entryLength += 2;      /* 0x02 bytes and null termination */
+        entryLength += 2;      /* 0x02 bytes and null termination */
                 
-                /* advance over this protocol entry */
+        /* advance over this protocol entry */
                namex += entryLength;
-                namep += entryLength;
-                tcounter++;            /* which proto entry we're looking at */
+        namep += entryLength;
+        tcounter++;            /* which proto entry we're looking at */
         }
 #ifndef NOMOREFILESFIX
        /* 
@@ -2289,6 +2333,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         * ie. the order in which it sends us the protocol list.
         *
         * Special handling for Windows 2000 clients (defect 11765 )
+     * <asanka:11Jun03> Proto signature is the same for Win XP. </>
         */
        if (tcounter == 6) {
               int i = 0;
@@ -2317,8 +2362,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                       */
               }
        }
-       // NOMOREFILESFIX
-#endif
+#endif /* NOMOREFILESFIX */
 
         if (NTProtoIndex != -1) {
                protoIndex = NTProtoIndex;
@@ -2338,13 +2382,13 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return CM_ERROR_INVAL;
        else if (NTProtoIndex != -1) {
                smb_SetSMBParm(outp, 0, protoIndex);
-                smb_SetSMBParmByte(outp, 1, 0);        /* share level security, no passwd encrypt */
-                smb_SetSMBParm(outp, 1, 8);    /* max multiplexed requests */
-                smb_SetSMBParm(outp, 2, 100);  /* max VCs per consumer/server connection */
-                smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
+        smb_SetSMBParmByte(outp, 1, 0);        /* share level security, no passwd encrypt */
+        smb_SetSMBParm(outp, 1, smb_maxMpxRequests);   /* max multiplexed requests */
+        smb_SetSMBParm(outp, 2, smb_maxVCPerServer);   /* max VCs per consumer/server connection */
+        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
                smb_SetSMBParmLong(outp, 5, 65536);     /* raw buffer size */
-                smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
-                smb_SetSMBParm(outp, 8, 1);
+        smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
+        smb_SetSMBParm(outp, 8, 1);
                /* 
                 * Tried changing the capabilities to support for W2K - defect 117695
                 * Maybe something else needs to be changed here?
@@ -2370,8 +2414,8 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 smb_SetSMBParm(outp, 0, protoIndex);
                 smb_SetSMBParm(outp, 1, 0);    /* share level security, no passwd encrypt */
                 smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
-                smb_SetSMBParm(outp, 3, 8);    /* max multiplexed requests */
-                smb_SetSMBParm(outp, 4, 100);  /* max VCs per consumer/server connection */
+                smb_SetSMBParm(outp, 3, smb_maxMpxRequests);   /* max multiplexed requests */
+                smb_SetSMBParm(outp, 4, smb_maxVCPerServer);   /* max VCs per consumer/server connection */
                 smb_SetSMBParm(outp, 5, 0);    /* no support of block mode for read or write */
                 smb_SetSMBParm(outp, 6, 1);    /* next 2: session key */
                 smb_SetSMBParm(outp, 7, 1);
@@ -2578,27 +2622,29 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
        /* names starting with a dot are illegal */
        if (*tp == '.') valid8Dot3 = 0;
 
-        for(i=0;; i++) {
+    for(i=0;; i++) {
                tc = *tp++;
-                if (tc == 0) return valid8Dot3;
-                if (tc == '.' || tc == '"') break;
-                if (i < 8) *up++ = tc;
-                else valid8Dot3 = 0;
-        }
+        if (tc == 0) return valid8Dot3;
+        if (tc == '.' || tc == '"') break;
+        if (i < 8) *up++ = tc;
+        else valid8Dot3 = 0;
+    }
         
-        /* if we get here, tp point after the dot */
-        up = maskp+8;  /* ext goes here */
-        for(i=0;;i++) {
-               tc = *tp++;
-                if (tc == 0) return valid8Dot3;
-               
-                /* too many dots */
-                if (tc == '.' || tc == '"') valid8Dot3 = 0;
+    /* if we get here, tp point after the dot */
+    up = maskp+8;      /* ext goes here */
+    for(i=0;;i++) {
+        tc = *tp++;
+        if (tc == 0) return valid8Dot3;
 
-               /* copy extension if not too long */
-                if (i < 3) *up++ = tc;
-                else valid8Dot3 = 0;
-        }
+        /* too many dots */
+        if (tc == '.' || tc == '"') valid8Dot3 = 0;
+
+        /* copy extension if not too long */
+        if (i < 3) *up++ = tc;
+        else valid8Dot3 = 0;
+    }   
+
+    /* unreachable */
 }
 
 int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
@@ -2743,6 +2789,10 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
                attr = smb_Attributes(scp);
                 *dptr++ = attr;
 
+        /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
+        if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+            attr |= SMB_ATTR_HIDDEN;
+
                /* get dos time */
                 smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
                 
@@ -2853,11 +2903,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                if (attribute & 0x8)
                        return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
 
-               osi_Log2(afsd_logp, "SMB receive search dir count %d |%s|",
+               osi_Log2(afsd_logp, "SMB receive search dir count %d [%s]",
                         maxCount, osi_LogSaveString(afsd_logp, pathp));
 
                if (*pathp == 0) {      /* null pathp, treat as root dir */
-                       if (!(attribute & 0x10))        /* exclude dirs */
+                       if (!(attribute & SMB_ATTR_DIRECTORY))  /* exclude dirs */
                                return CM_ERROR_NOFILES;
                        rootPath = 1;
                }
@@ -3115,15 +3165,20 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                        actualName = shortName;
                }
 
-                if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
-                       /* this is one of the entries to use: it is not deleted
-                        * and it matches the star pattern we're looking for.
-                         */
+            if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
+                /* this is one of the entries to use: it is not deleted
+                 * and it matches the star pattern we're looking for.
+                 */
 
-                        /* Eliminate entries that don't match requested
-                           attributes */
-                        if (!(dsp->attribute & 0x10))  /* no directories */
-                        {
+                /* Eliminate entries that don't match requested
+                   attributes */
+                 
+                /* no hidden files */
+                if(smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName))
+                    goto nextEntry;
+                
+                if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
+                {
                            /* We have already done the cm_TryBulkStat above */
                            fid.cell = scp->fid.cell;
                            fid.volume = scp->fid.volume;
@@ -3159,14 +3214,24 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                         * The replay will happen at a time when it is safe to
                         * unlock the directory.
                          */
-                       curPatchp = malloc(sizeof(*curPatchp));
-                        osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
-                        curPatchp->dptr = op;
-                       curPatchp->fid.cell = scp->fid.cell;
-                        curPatchp->fid.volume = scp->fid.volume;
-                        curPatchp->fid.vnode = ntohl(dep->fid.vnode);
-                        curPatchp->fid.unique = ntohl(dep->fid.unique);
-                       op += 9;        /* skip attr, time, date and size */
+                curPatchp = malloc(sizeof(*curPatchp));
+                osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
+                curPatchp->dptr = op;
+                curPatchp->fid.cell = scp->fid.cell;
+                curPatchp->fid.volume = scp->fid.volume;
+                curPatchp->fid.vnode = ntohl(dep->fid.vnode);
+                curPatchp->fid.unique = ntohl(dep->fid.unique);
+
+                /* do hidden attribute here since name won't be around when applying
+                 * dir list patches
+                 */
+
+                if ( smb_hideDotFiles && smb_IsDotFile(actualName) )
+                    curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+                else
+                    curPatchp->flags = 0;
+
+                op += 9;       /* skip attr, time, date and size */
                         
                        /* zero out name area.  The spec says to pad with
                         * spaces, but Samba doesn't, and neither do we.
@@ -3458,7 +3523,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         */
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastComp, pathp);
-       if (strcmp(lastComp, "\\desktop.ini") == 0) {
+       if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
                code = cm_NameI(rootScp, spacep->data,
                        caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
                        userp, tidPathp, &req, &dscp);
@@ -3500,13 +3565,21 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                 return code;
         }
 
+#ifdef undef
+    /* use smb_Attributes instead.   Also the fact that a file is in a readonly volume
+       doesn't mean it shojuld be marked as RO */
+
        if (newScp->fileType == CM_SCACHETYPE_DIRECTORY
                || newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-                       attrs = 0x10;
+                       attrs = SMB_ATTR_DIRECTORY;
        else
                attrs = 0;
        if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
-               attrs |= 1;     /* turn on read-only flag */
+               attrs |= SMB_ATTR_READONLY;     /* turn on read-only flag */
+#else
+    attrs = smb_Attributes(newScp);
+#endif
+
         smb_SetSMBParm(outp, 0, attrs);
         
         smb_DosUTimeFromUnixTime(&dosTime, newScp->clientModTime);
@@ -3564,11 +3637,21 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_InitReq(&req);
 
-       osi_Log0(afsd_logp, "SMB receive open");
-
-        pathp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(pathp, NULL);
+    pathp = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(pathp, NULL);
        
+    osi_Log1(afsd_logp, "SMB receive open file [%s]", osi_LogSaveString(afsd_logp, pathp));
+
+#ifdef DEBUG_VERBOSE
+    {
+        char *hexpath;
+
+        hexpath = osi_HexifyString( pathp );
+        DEBUG_EVENT2("AFS", "CoreOpen H[%s] A[%s]", hexpath, pathp);
+        free(hexpath);
+    }
+#endif
+
        share = smb_GetSMBParm(inp, 0);
         attribute = smb_GetSMBParm(inp, 1);
 
@@ -3914,22 +3997,21 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        rock.hasTilde = ((strchr(oldLastNamep, '~') != NULL) ? 1 : 0);
         rock.newNamep = newLastNamep;
 
-       /* now search the dir for the pattern, and do the appropriate rename when
-         * found.
-         */
-       thyper.LowPart = 0;             /* search dir from here */
-        thyper.HighPart = 0;
-       /* search for file to already exhist, if so return error*/
-
+    /* Check if the file already exists; if so return error */
        code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
        if((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
            cm_ReleaseSCache(tmpscp);
            return CM_ERROR_EXISTS; /* file exist, do not rename, also 
                                       fixes move*/
        }
-        code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
 
-        if (code == CM_ERROR_STOPNOW)
+    /* Now search the directory for the pattern, and do the appropriate rename when found */
+       thyper.LowPart = 0;             /* search dir from here */
+    thyper.HighPart = 0;
+
+    code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
+
+    if (code == CM_ERROR_STOPNOW)
                code = 0;
        else if (code == 0)
                code = CM_ERROR_NOSUCHFILE;
@@ -5127,7 +5209,17 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if (!smb_IsLegalFilename(lastNamep))
                 return CM_ERROR_BADNTFILENAME;
 
-        code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+    osi_Log1(afsd_logp, "SMB receive create [%s]", osi_LogSaveString( afsd_logp, pathp ));
+#ifdef DEBUG_VERBOSE
+    {
+        char *hexp;
+        hexp = osi_HexifyString( lastNamep );
+        DEBUG_EVENT2("AFS", "CoreCreate H[%s] A[%s]", hexp, lastNamep );
+        free(hexp);
+    }
+#endif    
+
+code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
         if (code && code != CM_ERROR_NOSUCHFILE) {
                cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
@@ -5410,6 +5502,10 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                 }
                 else {
                        /* bad opcode, fail the request, after displaying it */
+#ifdef NOTSERVICE
+            smb_LogPacket(inp);
+#endif  /* NOTSERVICE */
+
 #ifndef DJGPP
                        if (showErrors) {
                                sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
@@ -5439,6 +5535,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
                                    1, ncbp->ncb_length, ptbuf, smbp);
                        DeregisterEventSource(h);
+#ifdef NOTSERVICE
+            smb_LogPacket(inp);
+#endif /* NOTSERVICE */
 #else /* DJGPP */
             osi_Log1(afsd_logp, "Invalid SMB message, length %d",
                                  ncbp->ncb_length);
@@ -5686,8 +5785,9 @@ void smb_Server(VOID *parmp)
 
                code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                    FALSE, INFINITE);
-               if (code == WAIT_OBJECT_0)
+               if (code == WAIT_OBJECT_0) {
                        continue;
+        }
                idx_NCB = code - WAIT_OBJECT_0;
 
                ncbp = NCBs[idx_NCB];
@@ -5705,7 +5805,8 @@ void smb_Server(VOID *parmp)
 
                        case NRC_PENDING:
                                /* Can this happen? Or is it just my
-                                * UNIX paranoia? */
+                                * UNIX paranoia? 
+                 */
                                continue;
 
                        case NRC_SCLOSED:
@@ -5714,29 +5815,34 @@ void smb_Server(VOID *parmp)
                                dead_sessions[idx_session] = TRUE;
                                vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
                                /* Should also release vcp.  Also, would do
-                                * sanity check that all TID's are gone. */
-                               if (dead_vcp)
-                                       osi_Log1(afsd_logp,
-                                                "dead_vcp already set, %x",
-                                                dead_vcp);
-                               if (!dead_vcp
-                                    && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                                       osi_Log2(afsd_logp,
-                                                "setting dead_vcp %x, user struct %x",
-                                                vcp, vcp->usersp);
-                                       dead_vcp = vcp;
-                                       vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-                               }
-                               if (vcp->justLoggedOut) {
-                                       loggedOut = 1;
-                                       loggedOutTime = vcp->logoffTime;
-                                       loggedOutName =
-                                           strdup(vcp->justLoggedOut->unp->name);
-                                       loggedOutUserp = vcp->justLoggedOut;
-                                       lock_ObtainWrite(&smb_rctLock);
-                                       loggedOutUserp->refCount++;
-                                       lock_ReleaseWrite(&smb_rctLock);
-                               }
+                                * sanity check that all TID's are gone. 
+                 *
+                 * TODO: check if we could use LSNs[idx_session] instead, 
+                 * also cleanup after dead vcp 
+                 */
+                if (vcp) {
+                    if (dead_vcp)
+                        osi_Log1(afsd_logp,
+                                  "dead_vcp already set, %x",
+                                  dead_vcp);
+                    if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+                        osi_Log2(afsd_logp,
+                                  "setting dead_vcp %x, user struct %x",
+                                  vcp, vcp->usersp);
+                        dead_vcp = vcp;
+                        vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+                    }
+                    if (vcp->justLoggedOut) {
+                        loggedOut = 1;
+                        loggedOutTime = vcp->logoffTime;
+                        loggedOutName =
+                            strdup(vcp->justLoggedOut->unp->name);
+                        loggedOutUserp = vcp->justLoggedOut;
+                        lock_ObtainWrite(&smb_rctLock);
+                        loggedOutUserp->refCount++;
+                        lock_ReleaseWrite(&smb_rctLock);
+                    }
+                }
                                goto doneWithNCB;
 
                        case NRC_INCOMP:
@@ -5797,6 +5903,59 @@ void smb_Server(VOID *parmp)
                        smb_maxObsConcurrentCalls = smb_concurrentCalls;
 
                vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
+        /*
+               * If at this point vcp is NULL (implies that packet was invalid)
+               * then we are in big trouble. This means either :
+               *   a) we have the wrong NCB.
+               *   b) Netbios screwed up the call.
+               * Obviously this implies that 
+               *   ( LSNs[idx_session] != ncbp->ncb_lsn ||
+               *   lanas[idx_session] != ncbp->ncb_lana_num )
+               * Either way, we can't do anything with this packet.
+               * Log, sleep and resume.
+               */
+               if(!vcp) {
+                       HANDLE h;
+                       char buf[1000];
+                       char *ptbuf[1];
+
+                       sprintf(buf,
+                               "Bad vcp!! : "
+                               "LSNs[idx_session]=[%d],"
+                               "lanas[idx_session]=[%d],"
+                               "ncbp->ncb_lsn=[%d],"
+                               "ncbp->ncb_lana_num=[%d]",
+                               LSNs[idx_session],
+                               lanas[idx_session],
+                               ncbp->ncb_lsn,
+                               ncbp->ncb_lana_num);
+
+                       ptbuf[0] = buf;
+
+                       h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
+                       if(h) {
+                               ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,sizeof(*ncbp),ptbuf,(void*)ncbp);
+                               DeregisterEventSource(h);
+                       }
+
+                       /* Also log in the trace log. */
+                       osi_Log4(afsd_logp, "Server: BAD VCP!"
+                               "LSNs[idx_session]=[%d],"
+                               "lanas[idx_session]=[%d],"
+                               "ncbp->ncb_lsn=[%d],"
+                               "ncbp->ncb_lana_num=[%d]",
+                               LSNs[idx_session],
+                               lanas[idx_session],
+                               ncbp->ncb_lsn,
+                               ncbp->ncb_lana_num);
+
+                       /* thrd_Sleep(1000); Don't bother sleeping */
+                       thrd_SetEvent(SessionEvents[idx_session]);
+                       smb_concurrentCalls--;
+                       continue;
+               }
+
+
                vcp->errorCount = 0;
                bufp = (struct smb_packet *) ncbp->ncb_buffer;
 #ifdef DJGPP
@@ -5811,6 +5970,10 @@ void smb_Server(VOID *parmp)
                smbp = (smb_t *)bufp->data;
                outbufp->flags = 0;
 
+#if !defined(DJGPP) && !defined(AFS_WIN32_ENV)
+        __try
+        {
+#endif
                if (smbp->com == 0x1d) {
                        /* Special handling for Write Raw */
                        raw_write_cont_t rwc;
@@ -5846,8 +6009,14 @@ void smb_Server(VOID *parmp)
                        thrd_SetEvent(SessionEvents[idx_session]);
                 } else {
                        thrd_SetEvent(SessionEvents[idx_session]);
+            /* TODO: what else needs to be serialized? */
                        smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
                }
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
+        }
+        __except( smb_ServerExceptionFilter() ) {
+        }
+#endif
 
                smb_concurrentCalls--;
 
@@ -5857,6 +6026,34 @@ doneWithNCB:
 }
 
 /*
+ * Exception filter for the server threads.  If an exception occurs in the
+ * dispatch routines, which is where exceptions are most common, then do a
+ * force trace and give control to upstream exception handlers. Useful for
+ * debugging.
+ */
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
+DWORD smb_ServerExceptionFilter(void) {
+       /* While this is not the best time to do a trace, if it succeeds, then
+        * we have a trace (assuming tracing was enabled). Otherwise, this should
+        * throw a second exception.
+        */
+       HANDLE h;
+       char *ptbuf[1];
+
+       ptbuf[0] = "Unhandled exception forcing trace";
+
+       h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
+       if(h) {
+               ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,0,ptbuf,NULL);
+               DeregisterEventSource(h);
+       }
+
+       afsd_ForceTrace(TRUE);
+       return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+/*
  * Create a new NCB and associated events, packet buffer, and "space" buffer.
  * If the number of server threads is M, and the number of live sessions is
  * N, then the number of NCB's in use at any time either waiting for, or
@@ -5904,6 +6101,10 @@ void smb_Listener(void *parmp)
         dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
 #endif /* DJGPP */
 
+    /* retrieve computer name */
+    GetComputerName(cname, &cnamelen);
+    _strupr(cname);
+
        while (1) {
                memset(ncbp, 0, sizeof(NCB));
                flags = 0;
@@ -5969,9 +6170,8 @@ void smb_Listener(void *parmp)
                                break;
                        }
                }
-               /* get local name and compare */
-               GetComputerName(cname, &cnamelen);
-               _strupr(cname);
+
+        /* compare with local name */
                if (!isGateway)
                        if (strncmp(rname, cname, NCBNAMSZ) != 0)
                                flags |= SMB_VCFLAG_REMOTECONN;
@@ -5984,7 +6184,7 @@ void smb_Listener(void *parmp)
                sessionGen++;
 
                /* Log session startup */
-#ifdef NOSERVICE
+#ifdef NOTSERVICE
             fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host "
                                 "%s\n",
                   ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
@@ -6021,17 +6221,29 @@ void smb_Listener(void *parmp)
 
                /* Allocate slot in session arrays */
                /* Re-use dead session if possible, otherwise add one more */
-               for (i = 0; i < numSessions; i++) {
+        /* But don't look at session[0], it is reserved */
+               for (i = 1; i < numSessions; i++) {
                        if (dead_sessions[i]) {
                                dead_sessions[i] = FALSE;
                                break;
                        }
                }
+
+        /* assert that we do not exceed the maximum number of sessions or NCBs.
+         * we should probably want to wait for a session to be freed in case
+         * we run out.
+         */
+
+        osi_assert(i < Sessionmax && numNCBs < NCBmax - 1);
+
                LSNs[i] = ncbp->ncb_lsn;
                lanas[i] = ncbp->ncb_lana_num;
                
                if (i == numSessions) {
                        /* Add new NCB for new session */
+
+            osi_Log1(afsd_logp, "smb_Listener creating new session %d", i);
+
                        InitNCBslot(numNCBs);
                        numNCBs++;
                        thrd_SetEvent(NCBavails[0]);
@@ -6095,7 +6307,7 @@ void smb_NetbiosInit()
 #ifndef DJGPP
     if (smb_LANadapter == -1) {
         ncbp->ncb_command = NCBENUM;
-        ncbp->ncb_buffer = &lana_list;
+        ncbp->ncb_buffer = (PUCHAR)&lana_list;
         ncbp->ncb_length = sizeof(lana_list);
         code = Netbios(ncbp);
         if (code != 0) {
@@ -6346,8 +6558,9 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
         
         /* remember the name */
        len = strlen(snamep);
-        smb_localNamep = malloc(len+1);
-        strcpy(smb_localNamep, snamep);
+    smb_localNamep = malloc(len+1);
+    strcpy(smb_localNamep, snamep);
+    afsi_log("smb_localNamep is >%s<", smb_localNamep);
 
        /* and the global lock */
         lock_InitializeRWLock(&smb_globalLock, "smb global lock");
@@ -6439,7 +6652,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0x0b].procp = smb_ReceiveCoreWrite;
        smb_dispatchTable[0x0c].procp = smb_ReceiveCoreLockRecord;
        smb_dispatchTable[0x0d].procp = smb_ReceiveCoreUnlockRecord;
-       smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp;
+       smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp; /* create temporary */
        smb_dispatchTable[0x0f].procp = smb_ReceiveCoreCreate;
        smb_dispatchTable[0x10].procp = smb_ReceiveCoreCheckPath;
        smb_dispatchTable[0x11].procp = smb_SendCoreBadOp;      /* process exit */
@@ -6611,11 +6824,92 @@ void smb_Shutdown(void)
 }
 #endif /* DJGPP */
 
+/* Get the UNC \\<servername>\<sharename> prefix. */
+char *smb_GetSharename()
+{
+        char *name;
+
+       /* Make sure we have been properly initialized. */
+       if (smb_localNamep == NULL)
+               return NULL;
+
+        /* Allocate space for \\<servername>\<sharename>, plus the
+         * terminator.
+         */
+        name = malloc(strlen(smb_localNamep) + strlen("ALL") + 4);
+        sprintf(name, "\\\\%s\\%s", smb_localNamep, "ALL");
+        return name;
+}
+
+#ifdef NOTSERVICE
+
+void smb_LogPacket(smb_packet_t *packet)
+{
+       BYTE *vp, *cp;
+       unsigned length, paramlen, datalen, i, j;
+       char buf[81];
+       char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+       if(!packet) return;
+
+       osi_Log0(afsd_logp, "*** SMB packet dump ***");
+
+       vp = (BYTE *) packet->data;
+
+       datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1)));
+       length = paramlen + 2 + datalen;
+
+
+       for(i=0;i < length; i+=16)
+       {
+               memset( buf, ' ', 80 );
+               buf[80] = 0;
+
+               itoa( i, buf, 16 );
+
+               buf[strlen(buf)] = ' ';
+
+               cp = (BYTE*) buf + 7;
+
+               for(j=0;j < 16 && (i+j)<length; j++)
+               {
+                       *(cp++) = hex[vp[i+j] >> 4];
+                       *(cp++) = hex[vp[i+j] & 0xf];
+                       *(cp++) = ' ';
+
+                       if(j==7)
+                       {
+                               *(cp++) = '-';
+                               *(cp++) = ' ';
+                       }
+               }
+
+               for(j=0;j < 16 && (i+j)<length;j++)
+               {
+                       *(cp++) = ( 32 <= vp[i+j] && 128 > vp[i+j] )? vp[i+j]:'.';
+                       if(j==7)
+                       {
+                               *(cp++) = ' ';
+                               *(cp++) = '-';
+                               *(cp++) = ' ';
+                       }
+               }
+
+               *cp = 0;
+
+               osi_Log0( afsd_logp, buf );
+       }
+
+       osi_Log0(afsd_logp, "*** End SMB packet dump ***");
+
+}
+
+#endif /* NOTSERVICE */
+
 int smb_DumpVCP(FILE *outputFile, char *cookie)
 {
     int zilch;
     char output[1024];
-    int i;
   
     smb_vc_t *vcp;
   
index 874cfa5..e0663b7 100644 (file)
@@ -258,6 +258,18 @@ typedef struct smb_fid {
 #define SMB_FID_LOOKSLIKECOPY  (SMB_FID_LENGTHSETDONE | SMB_FID_MTIMESETDONE)
 #define SMB_FID_NTOPEN                 0x100   /* have dscp and pathp */
 
+/*
+ * SMB file attributes
+ */
+#define SMB_ATTR_ARCHIVE  0x20
+#define SMB_ATTR_COMPRESSED 0x800 /* file or dir is compressed */
+#define SMB_ATTR_NORMAL 0x80 /* normal file. Only valid if used alone */
+#define SMB_ATTR_HIDDEN 0x2 /* hidden file for the purpose of dir listings */
+#define SMB_ATTR_READONLY 0x1
+#define SMB_ATTR_TEMPORARY 0x100
+#define SMB_ATTR_DIRECTORY 0x10
+#define SMB_ATTR_SYSTEM 0x4
+
 /* for tracking in-progress directory searches */
 typedef struct smb_dirSearch {
        osi_queue_t q;                  /* queue of all outstanding cookies */
@@ -281,11 +293,16 @@ typedef struct smb_dirSearch {
 /* type for patching directory listings */
 typedef struct smb_dirListPatch {
        osi_queue_t q;
-        char *dptr;            /* ptr to attr, time, data, sizel, sizeh */
+    char *dptr;                /* ptr to attr, time, data, sizel, sizeh */
+    long flags;     /* flags.  See below */
        cm_fid_t fid;
   cm_dirEntry_t *dep;   /* temp */
 } smb_dirListPatch_t;
 
+/* dirListPatch Flags */
+#define SMB_DIRLISTPATCH_DOTFILE 1  /* the file referenced is a dot file 
+                                                                          Note: will not be set if smb_hideDotFiles is false */
+
 /* waiting lock list elements */
 typedef struct smb_waitingLock {
        osi_queue_t q;
@@ -428,6 +445,12 @@ extern osi_rwlock_t smb_rctLock;
 extern int smb_LogoffTokenTransfer;
 extern unsigned long smb_LogoffTransferTimeout;
 
+extern int smb_maxVCPerServer; /* max # of VCs per server */
+extern int smb_maxMpxRequests; /* max # of mpx requests */
+
+extern int smb_hideDotFiles;
+extern unsigned int smb_IsDotFile(char *lastComp);
+
 extern void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp,
        smb_packet_t *op);
 
@@ -461,6 +484,8 @@ extern long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count,
 
 extern BOOL smb_IsLegalFilename(char *filename);
 
+extern char *smb_GetSharename(void);
+
 /* include other include files */
 #include "smb3.h"
 #include "smb_ioctl.h"
@@ -468,4 +493,7 @@ extern BOOL smb_IsLegalFilename(char *filename);
 
 cm_user_t *smb_FindOrCreateUser(smb_vc_t *vcp, char *usern);
 
+#ifdef NOTSERVICE
+extern void smb_LogPacket(smb_packet_t *packet);
+#endif /* NOTSERVICE */
 #endif /* whole file */
index 7938f57..0a230d1 100644 (file)
@@ -7,8 +7,6 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
-//#define NOSERVICE 1 
-
 #include <afs/param.h>
 #include <afs/stds.h>
 
@@ -70,7 +68,7 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
 
        if (scp->fileType == CM_SCACHETYPE_DIRECTORY
            || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-               attrs = 0x10;
+               attrs = SMB_ATTR_DIRECTORY;
        else
                attrs = 0;
        /*
@@ -81,10 +79,10 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
        if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
 #endif
        if ((scp->unixModeBits & 0222) == 0)
-               attrs |= 1;             /* Read-only */
+               attrs |= SMB_ATTR_READONLY;             /* Read-only */
 
        if (attrs == 0)
-               attrs = 0x80;           /* FILE_ATTRIBUTE_NORMAL */
+               attrs = SMB_ATTR_NORMAL;                /* FILE_ATTRIBUTE_NORMAL */
 
        return attrs;
 }
@@ -164,6 +162,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         if (!userp)
           userp = cm_NewUser();
         lock_ObtainMutex(&vcp->mx);
+        if (!vcp->uidCounter)
+            vcp->uidCounter++; /* handle unlikely wraparounds */
         newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
         lock_ReleaseMutex(&vcp->mx);
 
@@ -203,8 +203,9 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
 
        /* find the tree and free it */
-        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-        if (uidp) {
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    /* TODO: smb_ReleaseUID() ? */
+    if (uidp) {
                char *s1 = NULL, *s2 = NULL;
 
                if (s2 == NULL) s2 = " ";
@@ -566,10 +567,15 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        parmCount, dataCount);
        }
 
-        /* now copy the parms and data */
+    /* now copy the parms and data */
+    if ( parmCount != 0 )
+    {
         memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
+    }
+    if ( dataCount != 0 ) {
         memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
-        
+    }
+
         /* account for new bytes */
         asp->curData += dataCount;
         asp->curParms += parmCount;
@@ -581,10 +587,17 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
                 lock_ReleaseWrite(&smb_globalLock);
                 
-                /* now dispatch it */
-                               osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
-                               osi_Log4(afsd_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
+            /* now dispatch it */
+            if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
+                osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
+                osi_Log4(afsd_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
                 code = (*smb_tran2DispatchTable[asp->opcode].procp)(vcp, asp, outp);
+            }
+            else {
+                osi_LogEvent("AFS-Dispatch-2 [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+                osi_Log4(afsd_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+                code = CM_ERROR_BADOP;
+            }
 
                /* if an error is returned, we're supposed to send an error packet,
                  * otherwise the dispatched function already did the data sending.
@@ -707,7 +720,24 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
                 return 0;
         }
 
+#ifdef DEBUG_VERBOSE
+       {
+               char *hexp, *asciip;
+               asciip = (lastNamep ? lastNamep : pathp);
+               hexp = osi_HexifyString( asciip );
+               DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip);
+               free(hexp);
+       }
+#endif
+
        userp = smb_GetTran2User(vcp, p);
+    /* In the off chance that userp is NULL, we log and abandon */
+    if(!userp) {
+        osi_Log1(afsd_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
+
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
        dscp = NULL;
@@ -776,7 +806,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
                }
                 else openAction = 1;   /* found existing file */
         }
-       else if (!(openFun & 0x10)) {
+       else if (!(openFun & SMB_ATTR_DIRECTORY)) {
                /* don't create if not found */
                 if (dscp) cm_ReleaseSCache(dscp);
                 osi_assert(scp == NULL);
@@ -858,8 +888,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
        if (extraInfo) {
                outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-                outp->parmsp[parmSlot] =  dosTime & 0xffff; parmSlot++;
-                outp->parmsp[parmSlot] = (dosTime>>16) & 0xffff; parmSlot++;
+                outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
+                outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
                 outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
                        parmSlot++;
                 outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
@@ -934,19 +964,19 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
 
         case 2:
                /* volume info */
-                qi.u.volumeInfo.vsn = 1234;
-                qi.u.volumeInfo.vnCount = 4;
+        qi.u.volumeInfo.vsn = 1234;
+        qi.u.volumeInfo.vnCount = 4;
                /* we're supposed to pad it out with zeroes to the end */
                memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
-                strcpy(qi.u.volumeInfo.label, "AFS");
+        memcpy(qi.u.volumeInfo.label, "AFS", 4);
                break;
 
        case 0x102:
                /* FS volume info */
                memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME));
                qi.u.FSvolumeInfo.vsn = 1234;
-               qi.u.FSvolumeInfo.vnCount = 4;
-               strcpy(qi.u.FSvolumeInfo.label, "AFS");
+               qi.u.FSvolumeInfo.vnCount = 8;
+               memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8);
                break;
 
        case 0x103:
@@ -1125,6 +1155,11 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         }
         
         userp = smb_GetTran2User(vcp, p);
+        if(!userp) {
+               osi_Log1(afsd_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
+               smb_FreeTran2Packet(outp);
+               return CM_ERROR_BADSMB;
+        }
 
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
@@ -1147,34 +1182,35 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                smb_StripLastComponent(spacep->data, &lastComp,
                                        (char *)(&p->parmsp[3]));
                /* Make sure that lastComp is not NULL */
-               if (lastComp)
+               if (lastComp) {
                    if (strcmp(lastComp, "\\desktop.ini") == 0) {
-                       code = cm_NameI(cm_rootSCachep, spacep->data,
-                                       CM_FLAG_CASEFOLD
-                                         | CM_FLAG_DIRSEARCH
-                                         | CM_FLAG_FOLLOW,
-                                       userp, tidPathp, &req, &dscp);
-                       if (code == 0) {
-                               if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
-                                   && !dscp->mountRootFidp)
-                                       code = CM_ERROR_NOSUCHFILE;
-                               else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
-                                       cm_buf_t *bp = buf_Find(dscp, &hzero);
-                                       if (bp)
-                                               buf_Release(bp);
-                                       else
-                                               code = CM_ERROR_NOSUCHFILE;
-                               }
-                               cm_ReleaseSCache(dscp);
-                               if (code) {
-                                       cm_FreeSpace(spacep);
-                                       cm_ReleaseUser(userp);
-                                       smb_SendTran2Error(vcp, p, opx, code);
-                                       smb_FreeTran2Packet(outp);
-                                       return 0;
-                               }
-                       }
-               }
+                code = cm_NameI(cm_rootSCachep, spacep->data,
+                                CM_FLAG_CASEFOLD
+                                | CM_FLAG_DIRSEARCH
+                                | CM_FLAG_FOLLOW,
+                                userp, tidPathp, &req, &dscp);
+                if (code == 0) {
+                    if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
+                         && !dscp->mountRootFidp)
+                        code = CM_ERROR_NOSUCHFILE;
+                    else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
+                        cm_buf_t *bp = buf_Find(dscp, &hzero);
+                        if (bp)
+                            buf_Release(bp);
+                        else
+                            code = CM_ERROR_NOSUCHFILE;
+                    }
+                    cm_ReleaseSCache(dscp);
+                    if (code) {
+                        cm_FreeSpace(spacep);
+                        cm_ReleaseUser(userp);
+                        smb_SendTran2Error(vcp, p, opx, code);
+                        smb_FreeTran2Packet(outp);
+                        return 0;
+                    }
+                }
+            }
+        }
                cm_FreeSpace(spacep);
        }
 
@@ -1317,6 +1353,11 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        outp->totalData = nbytesRequired;
 
        userp = smb_GetTran2User(vcp, p);
+    if(!userp) {
+       osi_Log1(afsd_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
        lock_ObtainMutex(&scp->mx);
@@ -1423,6 +1464,11 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        outp->totalData = 0;
 
        userp = smb_GetTran2User(vcp, p);
+    if(!userp) {
+       osi_Log1(afsd_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
 
@@ -1447,10 +1493,12 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                attr.mask = 0;
                
                lastMod = *((FILETIME *)(p->datap + 16));
-               /* when called as result of move a b, lastMod is (-1, -1). If the check for -1 is not present, timestamp
-               of the resulting file will be 1969 (-1)
+               /* when called as result of move a b, lastMod is (-1, -1). 
+         * If the check for -1 is not present, timestamp
+                * of the resulting file will be 1969 (-1)
                 */
-               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
+               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
+            lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
                        attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
                        smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
                                                        &lastMod);
@@ -1614,6 +1662,9 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
                        /* Copy attributes */
                        lattr = smb_ExtAttributes(scp);
                        *((u_long *)dptr) = lattr;
+            /* merge in hidden (dot file) attribute */
+                       if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                               lattr |= SMB_ATTR_HIDDEN;
                        dptr += 4;
                }
                else {
@@ -1660,6 +1711,9 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
                        /* finally copy out attributes as short */
                        attr = smb_Attributes(scp);
+            /* merge in hidden (dot file) attribute */
+            if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                attr |= SMB_ATTR_HIDDEN;
                        *dptr++ = attr & 0xff;
                        *dptr++ = (attr >> 8) & 0xff;
                }
@@ -1929,14 +1983,22 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                        osi_LogSaveString(afsd_logp, pathp));
         
         /* bail out if request looks bad */
-        if (p->opcode == 1 && !pathp) {
-                return CM_ERROR_BADSMB;
-        }
+    if (p->opcode == 1 && !pathp) {
+        smb_ReleaseDirSearch(dsp);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
         
        osi_Log2(afsd_logp, "T2 dir search cookie 0x%x, connection %d",
                nextCookie, dsp->cookie);
 
-       userp = smb_GetTran2User(vcp, p);
+       userp = smb_GetTran2User(vcp, p);
+    if (!userp) {
+       osi_Log1(afsd_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+       smb_ReleaseDirSearch(dsp);
+       smb_FreeTran2Packet(outp);
+       return CM_ERROR_BADSMB;
+    }
 
        /* try to get the vnode for the path name next */
        lock_ObtainMutex(&dsp->mx);
@@ -2038,31 +2100,33 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 curOffset.LowPart &= ~(2048-1);
                 curOffset.LowPart |= temp;
 
-               /* check if we've returned all the names that will fit in the
-                 * response packet; we check return count as well as the number
-                * of bytes requested.  We check the # of bytes after we find
-                * the dir entry, since we'll need to check its size.
-                 */
-               if (returnedNames >= maxCount) break;
+            /* check if we've passed the dir's EOF */
+            if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+                eos = 1;
+                break;
+            }
+
+            /* check if we've returned all the names that will fit in the
+             * response packet; we check return count as well as the number
+             * of bytes requested.  We check the # of bytes after we find
+             * the dir entry, since we'll need to check its size.
+             */
+            if (returnedNames >= maxCount) {
+                break;
+            }
                 
-                /* check if we've passed the dir's EOF */
-                if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
-                       eos = 1;
-                       break;
-               }
-                
-                /* see if we can use the bufferp we have now; compute in which
-                * page the current offset would be, and check whether that's
-                * the offset of the buffer we have.  If not, get the buffer.
-                */
-                thyper.HighPart = curOffset.HighPart;
-                thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
-                if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+            /* see if we can use the bufferp we have now; compute in which
+             * page the current offset would be, and check whether that's
+             * the offset of the buffer we have.  If not, get the buffer.
+             */
+            thyper.HighPart = curOffset.HighPart;
+            thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+            if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
                        /* wrong buffer */
-                        if (bufferp) {
-                               buf_Release(bufferp);
-                                bufferp = NULL;
-                       }
+                if (bufferp) {
+                    buf_Release(bufferp);
+                    bufferp = NULL;
+                       }   
                        lock_ReleaseMutex(&scp->mx);
                        lock_ObtainRead(&scp->bufCreateLock);
                         code = buf_Get(scp, &thyper, &bufferp);
@@ -2176,8 +2240,12 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
                         /* Eliminate entries that don't match requested
                            attributes */
-                        if (!(dsp->attribute & 0x10))  /* no directories */
-                        {
+                    if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && 
+                        smb_IsDotFile(dep->name))
+                        goto nextEntry; /* no hidden files */
+                    
+                    if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
+                    {
                             /* We have already done the cm_TryBulkStat above */
                             fid.cell = scp->fid.cell;
                             fid.volume = scp->fid.volume;
@@ -2282,6 +2350,13 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                                curPatchp->dptr = op;
                                if (infoLevel >= 0x101)
                                        curPatchp->dptr += 8;
+
+                if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
+                    curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+                }
+                else
+                    curPatchp->flags = 0;
+
                                curPatchp->fid.cell = scp->fid.cell;
                                curPatchp->fid.volume = scp->fid.volume;
                                curPatchp->fid.vnode = ntohl(dep->fid.vnode);
@@ -2457,8 +2532,12 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
-                 * (since IOCTL calls themselves aren't getting through).
-                 */
+         * (since IOCTL calls themselves aren't getting through).
+         */
+#ifdef NOTSERVICE
+        osi_Log0(afsd_logp, "IOCTL Open");
+#endif
+
                fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
                 smb_SetupIoctlFid(fidp, spacep);
 
@@ -2491,7 +2570,16 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 return 0;
         }
 
-       userp = smb_GetUser(vcp, inp);
+#ifdef DEBUG_VERBOSE
+    {
+       char *hexp, *asciip;
+       asciip = (lastNamep ? lastNamep : pathp );
+       hexp = osi_HexifyString(asciip);
+       DEBUG_EVENT2("AFS", "V3Open H[%s] A[%s]", hexp, asciip );
+       free(hexp);
+    }
+#endif
+    userp = smb_GetUser(vcp, inp);
 
        dscp = NULL;
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
@@ -2887,9 +2975,16 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         
         if (searchTime != 0) {
                smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+
+            if ( unixTime != -1 ) {
                 attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
                 attrs.clientModTime = unixTime;
                 code = cm_SetAttr(scp, &attrs, userp, &req);
+
+                osi_Log1(afsd_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
+            } else {
+                osi_Log1(afsd_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+            }
         }
         else code = 0;
 
@@ -2993,11 +3088,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        cm_scache_t *scp;               /* file to create or open */
        cm_attr_t setAttr;
        char *lastNamep;
+    char *treeStartp;
        unsigned short nameLength;
        unsigned int flags;
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
+    unsigned int treeCreate;
        int realDirFlag;
        unsigned int desiredAccess;
        unsigned int extAttributes;
@@ -3019,6 +3116,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_InitReq(&req);
 
+    treeCreate = FALSE;
        foundscp = FALSE;
        scp = NULL;
 
@@ -3071,6 +3169,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
 
+    osi_Log1(afsd_logp,"NTCreateX for [%s]",osi_LogSaveString(afsd_logp,realPathp));
+    osi_Log4(afsd_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
+
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
                 * (since IOCTL calls themselves aren't getting through).
@@ -3107,19 +3208,41 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return 0;
        }
 
-       userp = smb_GetUser(vcp, inp);
+#ifdef DEBUG_VERBOSE
+    {
+       char *hexp, *asciip;
+       asciip = (lastNamep? lastNamep : realPathp);
+       hexp = osi_HexifyString( asciip );
+       DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
+       free(hexp);
+    }
+#endif
+    userp = smb_GetUser(vcp, inp);
+    if (!userp) {
+       osi_Log1(afsd_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if (!baseFidp) {
+               osi_Log1(afsd_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
 
-       /* compute open mode */
+    osi_Log1(afsd_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(afsd_logp,tidPathp));
+       
+    /* compute open mode */
        fidflags = 0;
        if (desiredAccess & DELETE)
                fidflags |= SMB_FID_OPENDELETE;
@@ -3136,25 +3259,65 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (code != 0
            || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
                /* look up parent directory */
-               code = cm_NameI(baseDirp, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_CHECKPATH,
-                               userp, tidPathp, &req, &dscp);
+        /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
+        the immediate parent.  We have to work our way up realPathp until we hit something that we
+        recognize.
+        */
+
+        while(1) {
+            char *tp;
+
+            code = cm_NameI(baseDirp, spacep->data,
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                             userp, tidPathp, &req, &dscp);
+
+            if(code && 
+                (tp = strrchr(spacep->data,'\\')) &&
+                (createDisp == 2) &&
+                (realDirFlag == 1)) {
+                *tp++ = 0;
+                treeCreate = TRUE;
+                treeStartp = realPathp + (tp - spacep->data);
+
+                if(*tp && !smb_IsLegalFilename(tp)) {
+                    if(baseFid != 0) smb_ReleaseFID(baseFidp);
+                    cm_ReleaseUser(userp);
+                    free(realPathp);
+                    return CM_ERROR_BADNTFILENAME;
+                }
+            }
+            else
+                break;
+        }
 
-               if (baseFid != 0) smb_ReleaseFID(baseFidp);
+        if (baseFid != 0) smb_ReleaseFID(baseFidp);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
-                       free(realPathp);
-                       return code;
-               }
+        if (code) {
+            osi_Log0(afsd_logp,"NTCreateX parent not found");
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return code;
+        }
 
-               if (!lastNamep) lastNamep = realPathp;
-               else lastNamep++;
+        if(treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
+            /* A file exists where we want a directory. */
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_EXISTS;
+        }
 
-                if (!smb_IsLegalFilename(lastNamep))
-                        return CM_ERROR_BADNTFILENAME;
+        if (!lastNamep) lastNamep = realPathp;
+        else lastNamep++;
 
-               if (!foundscp) {
+        if (!smb_IsLegalFilename(lastNamep)) {
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_BADNTFILENAME;
+        }
+
+        if (!foundscp && !treeCreate) {
                        code = cm_Lookup(dscp, lastNamep,
                                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                                         userp, &req, &scp);
@@ -3175,7 +3338,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         * by dscp, or we may have found the file directly.  If code is non-zero,
         * scp is NULL.
         */
-       if (code == 0) {
+       if (code == 0 && !treeCreate) {
                code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
                                      &req);
                if (code) {
@@ -3246,48 +3409,95 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                }
        }
        else {
-               /* create directory */
-               osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+        char *tp, *pp;
+        char *cp; /* This component */
+        int clen; /* length of component */
+        cm_scache_t *tscp;
+        int isLast = 0;
+               
+        /* create directory */
+               if ( !treeCreate ) treeStartp = lastNamep;
+        osi_assert(dscp != NULL);
+        osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+                               osi_LogSaveString(afsd_logp, treeStartp));
                openAction = 2;         /* created directory */
+
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                setAttr.clientModTime = time(NULL);
-               code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
-               if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                       smb_NotifyChange(FILE_ACTION_ADDED,
-                                        FILE_NOTIFY_CHANGE_DIR_NAME,
-                                        dscp, lastNamep, NULL, TRUE);
-               if (code == 0
-                   || (code == CM_ERROR_EXISTS && createDisp != 2)) {
-                       /* Not an exclusive create, and someone else tried
-                        * creating it already, then we open it anyway.  We
-                        * don't bother retrying after this, since if this next
-                        * fails, that means that the file was deleted after we
-                        * started this call.
-                        */
-                       code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
+               
+               pp = treeStartp;
+               cp = spacep->data;
+               tscp = dscp;
+
+               while(pp && *pp) {
+                       tp = strchr(pp, '\\');
+                       if(!tp) {
+                               strcpy(cp,pp);
+                               isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
+                       }
+                       else {
+                               clen = tp - pp;
+                               strncpy(cp,pp,clen);
+                               *(cp + clen) = 0;
+                               tp++;
+                       }
+                       pp = tp;
+
+                       if(clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */
+
+                       /* cp is the next component to be created. */
+                       code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
+                       if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
+                               smb_NotifyChange(FILE_ACTION_ADDED,
+                               FILE_NOTIFY_CHANGE_DIR_NAME,
+                               tscp, cp, NULL, TRUE);
+                       if (code == 0 || 
+                               (code == CM_ERROR_EXISTS && createDisp != 2)) {
+                                       /* Not an exclusive create, and someone else tried
+                                       * creating it already, then we open it anyway.  We
+                                       * don't bother retrying after this, since if this next
+                                       * fails, that means that the file was deleted after we
+                                       * started this call.
+                                       */
+                                       code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
+                                               userp, &req, &scp);
+                               }
+                       if(code) break;
+
+                       if(!isLast) { /* for anything other than dscp, release it unless it's the last one */
+                               cm_ReleaseSCache(tscp);
+                               tscp = scp; /* Newly created directory will be next parent */
+                       }
                }
+
+               /* 
+               if we get here and code == 0, then scp is the last directory created, and tscp is the
+               parent of scp.  dscp got released if dscp != tscp. both tscp and scp are held.
+               */
+               dscp = tscp;
        }
 
        if (code) {
                /* something went wrong creating or truncating the file */
                if (scp) cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return code;
        }
 
-       /* make sure we have file vs. dir right */
+       /* make sure we have file vs. dir right (only applies for single component case) */
        if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return CM_ERROR_ISDIR;
        }
+    /* (only applies to single component case) */
        if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return CM_ERROR_NOTDIR;
@@ -3346,6 +3556,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_ReleaseUser(userp);
 
+    /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */
+
        /* leave scp held since we put it in fidp->scp */
        return 0;
 }
@@ -3369,10 +3581,18 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
+    unsigned int extendedRespRequired;
        int realDirFlag;
        unsigned int desiredAccess;
+#ifdef DEBUG_VERBOSE    
+    unsigned int allocSize;
+    unsigned int shareAccess;
+#endif
        unsigned int extAttributes;
        unsigned int createDisp;
+#ifdef DEBUG_VERBOSE
+    unsigned int sdLen;
+#endif
        unsigned int createOptions;
        int initialModeBits;
        unsigned short baseFid;
@@ -3405,6 +3625,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        requestOpLock = flags & 0x02;
        requestBatchOpLock = flags & 0x04;
        mustBeDir = flags & 0x08;
+    extendedRespRequired = flags & 0x10;
+
        /*
         * Why all of a sudden 32-bit FID?
         * We will reject all bits higher than 16.
@@ -3413,11 +3635,26 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                return CM_ERROR_INVAL;
        baseFid = (unsigned short)lparmp[1];
        desiredAccess = lparmp[2];
+#ifdef DEBUG_VERBOSE
+    allocSize = lparmp[3];
+#endif /* DEBUG_VERSOSE */
        extAttributes = lparmp[5];
+#ifdef DEBUG_VEROSE
+    shareAccess = lparmp[6];
+#endif
        createDisp = lparmp[7];
        createOptions = lparmp[8];
+#ifdef DEBUG_VERBOSE
+    sdLen = lparmp[9];
+#endif
        nameLength = lparmp[11];
 
+#ifdef DEBUG_VERBOSE
+       osi_Log4(afsd_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+       osi_Log2(afsd_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
+       osi_Log1(afsd_logp,"... flags[%x]",flags);
+#endif
+
        /* mustBeDir is never set; createOptions directory bit seems to be
          * more important
         */
@@ -3449,14 +3686,35 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         * Will add it if necessary.
         */
 
+#ifdef DEBUG_VERBOSE
+       {
+               char *hexp, *asciip;
+               asciip = (lastNamep? lastNamep : realPathp);
+               hexp = osi_HexifyString( asciip );
+               DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip);
+               free(hexp);
+       }
+#endif
+
        userp = smb_GetUser(vcp, inp);
+    if(!userp) {
+       osi_Log1(afsd_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if(!baseFidp) {
+               osi_Log1(afsd_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
@@ -3664,53 +3922,107 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        /* set inp->fid so that later read calls in same msg can find fid */
        inp->fid = fidp->fid;
 
-       /* out parms */
-       parmOffset = 8*4 + 39;
-       parmOffset += 1;        /* pad to 4 */
-       dataOffset = parmOffset + 70;
+    /* check whether we are required to send an extended response */
+    if (!extendedRespRequired) {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 70;
+
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+        /* Parameter Offset */
+        smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+        /* Parameter Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Offset */
+        smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+        /* Data Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+        smb_SetSMBDataLength(outp, 70);
 
-       parmSlot = 1;
-       outp->oddByte = 1;
-       /* Total Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
-       /* Total Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
-       /* Parameter Offset */
-       smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
-       /* Parameter Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Data Offset */
-       smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
-       /* Data Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       smb_SetSMBParmByte(outp, parmSlot, 0);  /* Setup Count */
-       smb_SetSMBDataLength(outp, 70);
-
-       lock_ObtainMutex(&scp->mx);
-       outData = smb_GetSMBData(outp, NULL);
-       outData++;                      /* round to get to parmOffset */
-       *outData = 0; outData++;        /* oplock */
-       *outData = 0; outData++;        /* reserved */
-       *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
-       *((ULONG *)outData) = openAction; outData += 4;
-       *((ULONG *)outData) = 0; outData += 4;  /* EA error offset */
-       smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-       *((FILETIME *)outData) = ft; outData += 8;      /* creation time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* last access time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* last write time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* change time */
-       *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
-       *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
-       *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
-       *((USHORT *)outData) = 0; outData += 2; /* filetype */
-       *((USHORT *)outData) = 0; outData += 2; /* dev state */
-       *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
-                                outData += 2;  /* is a dir? */
-       lock_ReleaseMutex(&scp->mx);
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 0; outData++;       /* reserved */
+        *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
+        *((ULONG *)outData) = openAction; outData += 4;
+        *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+        *((USHORT *)outData) = 0; outData += 2;        /* filetype */
+        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 2;  /* is a dir? */
+        lock_ReleaseMutex(&scp->mx);
+    } else {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 104;
+        
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+        /* Parameter Offset */
+        smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+        /* Parameter Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Offset */
+        smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+        /* Data Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+        smb_SetSMBDataLength(outp, 105);
+        
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 1; outData++;       /* response type */
+        *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
+        *((ULONG *)outData) = openAction; outData += 4;
+        *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+        *((USHORT *)outData) = 0; outData += 2;        /* filetype */
+        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 1;  /* is a dir? */
+        memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+        *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
+        *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
+        lock_ReleaseMutex(&scp->mx);
+    }
 
        osi_Log1(afsd_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
 
@@ -3718,6 +4030,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
        cm_ReleaseUser(userp);
 
+       /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
        /* leave scp held since we put it in fidp->scp */
        return 0;
 }
@@ -3733,10 +4046,16 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
        filter = smb_GetSMBParm(inp, 19)
                        | (smb_GetSMBParm(inp, 20) << 16);
        fid = smb_GetSMBParm(inp, 21);
-       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;
+       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;  /* TODO: should this be 0xff ? */
+
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        osi_Log1(afsd_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+        return CM_ERROR_BADFD;
+    }
 
        savedPacketp = smb_CopyPacket(inp);
-       savedPacketp->vcp = vcp;
+       savedPacketp->vcp = vcp; /* TODO: refcount vcp? */
        lock_ObtainMutex(&smb_Dir_Watch_Lock);
        savedPacketp->nextp = smb_Directory_Watches;
        smb_Directory_Watches = savedPacketp;
@@ -3903,7 +4222,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                filter = smb_GetSMBParm(watch, 19)
                                | (smb_GetSMBParm(watch, 20) << 16);
                fid = smb_GetSMBParm(watch, 21);
-               wtree = smb_GetSMBParm(watch, 22) & 0xffff;
+               wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
                maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
                                | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
                vcp = watch->vcp;
@@ -3916,6 +4235,11 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                        filter = 0x17;
 
                fidp = smb_FindFID(vcp, fid, 0);
+        if (!fidp) {
+               lastWatch = watch;
+               watch = watch->nextp;
+               continue;
+        }
                if (fidp->scp != dscp
                    || (filter & notifyFilter) == 0
                    || (!isDirectParent && !wtree)) {
@@ -4065,19 +4389,22 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
 
                        fidp = smb_FindFID(vcp, fid, 0);
-                        
-                        osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s", 
-                                fid, watchtree,
-                                                               osi_LogSaveString(afsd_logp, (fidp)?fidp->NTopen_wholepathp:""));
-
-                       scp = fidp->scp;
-                       lock_ObtainMutex(&scp->mx);
-                       if (watchtree)
-                               scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
-                       else
-                               scp->flags &= ~CM_SCACHEFLAG_WATCHED;
-                       lock_ReleaseMutex(&scp->mx);
-                       smb_ReleaseFID(fidp);
+            if (fidp) {
+                osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s", 
+                         fid, watchtree,
+                         osi_LogSaveString(afsd_logp, (fidp)?fidp->NTopen_wholepathp:""));
+
+                scp = fidp->scp;
+                lock_ObtainMutex(&scp->mx);
+                if (watchtree)
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+                else
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+                lock_ReleaseMutex(&scp->mx);
+                smb_ReleaseFID(fidp);
+            } else {
+                osi_Log2(afsd_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
+            }
 
                        /* assume STATUS32; return 0xC0000120 (CANCELED) */
                        replyWctp = watch->wctp;
@@ -4108,7 +4435,6 @@ void smb3_Init()
 
 cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
 {
-    cm_user_t *userp;
     /*int newUid;*/
     smb_username_t *unp;
 
index 99b41e9..b8391d3 100644 (file)
@@ -205,8 +205,8 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
 
         op = smb_GetSMBData(outp, NULL);
         *op++ = 1;
-        *op++ = count & 0xff;
-        *op++ = (count >> 8) & 0xff;
+        *op++ = (char)(count & 0xff);
+        *op++ = (char)((count >> 8) & 0xff);
         
        /* now copy the data into the response packet */
         memcpy(op, iop->outCopied + iop->outAllocp, count);
@@ -293,7 +293,7 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                    osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
                             userp);
                }
-               smb_ReleaseUID(uidp);
+               if (uidp) smb_ReleaseUID(uidp);
        }
 
        iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
@@ -381,10 +381,13 @@ long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
                    osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
                             uidp->userID, userp,
                             osi_LogSaveString(afsd_logp, uidp->unp->name));
-               else
+               else if (uidp)
                    osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
                             uidp->userID, userp);
-               smb_ReleaseUID(uidp);
+        else 
+                   osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
+                            userp);
+               if (uidp) smb_ReleaseUID(uidp);
        }
 
        iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
index ccccece..b8f2c8c 100644 (file)
@@ -69,7 +69,7 @@ $(EXEFILE): $(EXEOBJS) $(EXELIBS)
 ############################################################################
 # Definitions for generating versioninfo resource via RC
 
-$(OUT)\afscfg_stub.res: AFS_component_version_number.h
+$(OUT)\afscfg_stub.res:afscfg_stub.rc AFS_component_version_number.h
 
 ############################################################################
 # Install target; primary makefile target
@@ -82,7 +82,7 @@ install: $(EXEFILE) lang
 
 lang::
        $(CD) lang
-       for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile install
+       for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /e /f NTMakefile install
        $(CD) ..
 
 
index 3c5210b..487e7b2 100644 (file)
@@ -34,7 +34,7 @@ $(DLLFILE): $(DLLOBJS)
 ############################################################################
 # Definitions for generating versioninfo resource via RC
 
-$(OUT)\afssvrcpa_stub.res: AFS_component_version_number.h
+$(OUT)\afssvrcpa_stub.res: afssvrcpa_stub.rc AFS_component_version_number.h
 
 ############################################################################
 # Install target; primary makefile target
@@ -47,7 +47,7 @@ install: $(DLLFILE) lang
 
 lang::
        $(CD) lang
-       for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile install
+       for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /e /f NTMakefile install
        $(CD) ..
 
 
index a6c63f5..c18cee5 100644 (file)
@@ -7,7 +7,7 @@
 
 # include the AFSD source tree on our inclusion path
 
-AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) -I..\afsd
+AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" -I..\afsd
 
 # include the primary makefile
 RELDIR=WINNT\client_config
@@ -36,7 +36,10 @@ EXEOBJS = \
        $(OUT)\dlg_diag.obj \
        $(OUT)\dlg_misc.obj \
        $(OUT)\isadmin.obj \
-       $(OUT)\dlg_automap.obj
+       $(OUT)\dlg_automap.obj \
+    $(OUT)\dlg_binding.obj \
+    $(OUT)\RegistrySupport.obj \
+    $(OUT)\getlana.obj
 
 EXEOBJSc = \
        $(OUT)\cellservdb.obj
@@ -52,7 +55,8 @@ AFSD= ..\afsd
 VCLIBS =\
        comctl32.lib \
        shell32.lib \
-       mpr.lib
+       mpr.lib \
+    netapi32.lib
 
 EXELIBS = \
        $(DESTDIR)\lib\afs\TaLocale.lib \
@@ -131,61 +135,61 @@ lang:: en_US ja_JP ko_KR zh_TW zh_CN pt_BR es_ES de_DE
 
 en_US:
        $(CD) lang
-       $(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       $(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 ja_JP:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 ko_KR:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 zh_CN:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 zh_TW:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 pt_BR:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 es_ES:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
 de_DE:
        $(CD) lang
-       @$(NTLANG) $@ $(MAKECMD) /nologo /f NTMakefile install
+       @$(NTLANG) $@ $(MAKECMD) /nologo /e /f NTMakefile install
     $(CD) ..
 
-$(OUT)\afs_config_stub.res : AFS_component_version_number.h
+$(OUT)\afs_config_stub.res : afs_config_stub.rc AFS_component_version_number.h
 
 clean::
        $(DEL) $(COPYHEADERS)
        $(CD) lang
-       if exist $(NTLANG) $(NTLANG) en_US $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) ja_JP $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) ko_KR $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) zh_CN $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) zh_TW $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) pt_BR $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) es_ES $(MAKECMD) /nologo /f NTMakefile clean
-       if exist $(NTLANG) $(NTLANG) de_DE $(MAKECMD) /nologo /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) en_US $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) ja_JP $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) ko_KR $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) zh_CN $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) zh_TW $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) pt_BR $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) es_ES $(MAKECMD) /nologo /e /f NTMakefile clean
+       if exist $(NTLANG) $(NTLANG) de_DE $(MAKECMD) /nologo /e /f NTMakefile clean
     $(CD) ..
 
 mkdir:
        -mkdir $(OUT)\lang
        cd lang
-       nmake /nologo /f ntmakefile SRC=$(SRC) OBJ=$(OBJ) mkdir
+       nmake /nologo /e /f ntmakefile SRC=$(SRC) OBJ=$(OBJ) mkdir
        cd ..
diff --git a/src/WINNT/client_config/RegistrySupport.cpp b/src/WINNT/client_config/RegistrySupport.cpp
new file mode 100644 (file)
index 0000000..cf87a18
--- /dev/null
@@ -0,0 +1,132 @@
+/*det
+ * Configuration Read/Modify Functions ________________________________________
+ *
+ * Temporarily these just modify the local Registry.
+ * In the near future, they will modify the Registry on the
+ * gateway, if a gateway is being used.
+ *
+ */
+
+#include <windows.h>
+#include <tchar.h>
+//#include <ctype.h>
+#include <stdlib.h>
+#include <drivemap.h>
+
+BOOL Config_ReadString (LPCTSTR pszLHS, LPTSTR pszRHS, size_t cchMax);
+
+extern TCHAR AFSConfigKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
+
+void Config_GetGlobalDriveList (DRIVEMAPLIST *pDriveList)
+{
+   // Read the GlobalAutoMapper registry key
+   TCHAR szDriveToMapTo[5];
+   DWORD dwResult;
+   TCHAR szKeyName[256];
+   HKEY hKey;
+   DWORD dwIndex = 0;
+   DWORD dwDriveSize;
+   DWORD dwSubMountSize;
+   TCHAR szSubMount[256];
+   DWORD dwType;
+
+   if (!pDriveList)
+      return;
+
+   memset(pDriveList, 0, sizeof(DRIVEMAPLIST));
+
+   lstrcpy(szKeyName, AFSConfigKeyName);
+   lstrcat(szKeyName, TEXT("\\GlobalAutoMapper"));
+
+   dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
+   if (dwResult != ERROR_SUCCESS)
+      return;
+
+   // Get the drive map list so we can lookup the paths that go with our submounts
+       DRIVEMAPLIST DriveMapList;
+   memset(&DriveMapList, 0, sizeof(DRIVEMAPLIST));
+   QueryDriveMapList (&DriveMapList);
+
+   while (1) {
+      dwDriveSize = sizeof(szDriveToMapTo);
+      dwSubMountSize = sizeof(szSubMount);
+      
+      dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, (BYTE*)szSubMount, &dwSubMountSize);
+      if (dwResult != ERROR_SUCCESS)
+         break;
+      
+      szDriveToMapTo[0] = _totupper(szDriveToMapTo[0]);
+        
+      int nCurDrive = szDriveToMapTo[0] - TEXT('A');
+       
+      pDriveList->aDriveMap[nCurDrive].chDrive = szDriveToMapTo[0];
+      lstrcpy(pDriveList->aDriveMap[nCurDrive].szSubmount, szSubMount);
+
+      // Find the path that goes with this submount
+      SubmountToPath (&DriveMapList, pDriveList->aDriveMap[nCurDrive].szMapping, szSubMount, FALSE);
+   }        
+
+   FreeDriveMapList(&DriveMapList);
+
+   RegCloseKey(hKey);
+}
+
+BOOL Config_ReadNum (LPCTSTR pszLHS, DWORD *pdwRHS)
+{
+   HKEY hk;
+   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS)
+      return FALSE;
+
+   DWORD dwSize = sizeof(*pdwRHS);
+   if (RegQueryValueEx (hk, pszLHS, NULL, NULL, (PBYTE)pdwRHS, &dwSize) != ERROR_SUCCESS)
+      {
+      RegCloseKey (hk);
+      return FALSE;
+      }
+
+   RegCloseKey (hk);
+   return TRUE;
+}
+
+
+BOOL Config_ReadString (LPCTSTR pszLHS, LPTSTR pszRHS, size_t cchMax)
+{
+   HKEY hk;
+   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS)
+      return FALSE;
+
+   DWORD dwSize = sizeof(TCHAR) * cchMax;
+   if (RegQueryValueEx (hk, pszLHS, NULL, NULL, (PBYTE)pszRHS, &dwSize) != ERROR_SUCCESS)
+      {
+      RegCloseKey (hk);
+      return FALSE;
+      }
+
+   RegCloseKey (hk);
+   return TRUE;
+}
+
+
+void Config_WriteNum (LPCTSTR pszLHS, DWORD dwRHS)
+{
+   HKEY hk;
+   DWORD dwDisp;
+   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
+      {
+      RegSetValueEx (hk, pszLHS, NULL, REG_DWORD, (PBYTE)&dwRHS, sizeof(dwRHS));
+      RegCloseKey (hk);
+      }
+}
+
+
+void Config_WriteString (LPCTSTR pszLHS, LPCTSTR pszRHS)
+{
+   HKEY hk;
+   DWORD dwDisp;
+   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
+      {
+      RegSetValueEx (hk, pszLHS, NULL, REG_SZ, (PBYTE)pszRHS, sizeof(TCHAR) * (1+lstrlen(pszRHS)));
+      RegCloseKey (hk);
+      }
+}
+
index 69b40c3..b9d82e7 100644 (file)
@@ -891,126 +891,3 @@ BOOL Config_SetReportSessionStartups (BOOL fFlag, ULONG *pStatus)
    return TRUE;
 }
 
-void Config_GetGlobalDriveList (DRIVEMAPLIST *pDriveList)
-{
-   // Read the GlobalAutoMapper registry key
-   TCHAR szDriveToMapTo[5];
-   DWORD dwResult;
-   TCHAR szKeyName[256];
-   HKEY hKey;
-   DWORD dwIndex = 0;
-   DWORD dwDriveSize;
-   DWORD dwSubMountSize;
-   TCHAR szSubMount[256];
-   DWORD dwType;
-
-   if (!pDriveList)
-      return;
-
-   memset(pDriveList, 0, sizeof(DRIVEMAPLIST));
-
-   lstrcpy(szKeyName, AFSConfigKeyName);
-   lstrcat(szKeyName, TEXT("\\GlobalAutoMapper"));
-
-   dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
-   if (dwResult != ERROR_SUCCESS)
-      return;
-
-   // Get the drive map list so we can lookup the paths that go with our submounts
-       DRIVEMAPLIST DriveMapList;
-   memset(&DriveMapList, 0, sizeof(DRIVEMAPLIST));
-   QueryDriveMapList (&DriveMapList);
-
-   while (1) {
-      dwDriveSize = sizeof(szDriveToMapTo);
-      dwSubMountSize = sizeof(szSubMount);
-      
-      dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, (BYTE*)szSubMount, &dwSubMountSize);
-      if (dwResult != ERROR_SUCCESS)
-         break;
-      
-      szDriveToMapTo[0] = _totupper(szDriveToMapTo[0]);
-        
-      int nCurDrive = szDriveToMapTo[0] - TEXT('A');
-       
-      pDriveList->aDriveMap[nCurDrive].chDrive = szDriveToMapTo[0];
-      lstrcpy(pDriveList->aDriveMap[nCurDrive].szSubmount, szSubMount);
-
-      // Find the path that goes with this submount
-      SubmountToPath (&DriveMapList, pDriveList->aDriveMap[nCurDrive].szMapping, szSubMount, FALSE);
-   }        
-
-   FreeDriveMapList(&DriveMapList);
-
-   RegCloseKey(hKey);
-}
-
-
-/*
- * Configuration Read/Modify Functions ________________________________________
- *
- * Temporarily these just modify the local Registry.
- * In the near future, they will modify the Registry on the
- * gateway, if a gateway is being used.
- *
- */
-
-BOOL Config_ReadNum (LPCTSTR pszLHS, DWORD *pdwRHS)
-{
-   HKEY hk;
-   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS)
-      return FALSE;
-
-   DWORD dwSize = sizeof(*pdwRHS);
-   if (RegQueryValueEx (hk, pszLHS, NULL, NULL, (PBYTE)pdwRHS, &dwSize) != ERROR_SUCCESS)
-      {
-      RegCloseKey (hk);
-      return FALSE;
-      }
-
-   RegCloseKey (hk);
-   return TRUE;
-}
-
-
-BOOL Config_ReadString (LPCTSTR pszLHS, LPTSTR pszRHS, size_t cchMax)
-{
-   HKEY hk;
-   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS)
-      return FALSE;
-
-   DWORD dwSize = sizeof(TCHAR) * cchMax;
-   if (RegQueryValueEx (hk, pszLHS, NULL, NULL, (PBYTE)pszRHS, &dwSize) != ERROR_SUCCESS)
-      {
-      RegCloseKey (hk);
-      return FALSE;
-      }
-
-   RegCloseKey (hk);
-   return TRUE;
-}
-
-
-void Config_WriteNum (LPCTSTR pszLHS, DWORD dwRHS)
-{
-   HKEY hk;
-   DWORD dwDisp;
-   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
-      {
-      RegSetValueEx (hk, pszLHS, NULL, REG_DWORD, (PBYTE)&dwRHS, sizeof(dwRHS));
-      RegCloseKey (hk);
-      }
-}
-
-
-void Config_WriteString (LPCTSTR pszLHS, LPCTSTR pszRHS)
-{
-   HKEY hk;
-   DWORD dwDisp;
-   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
-      {
-      RegSetValueEx (hk, pszLHS, NULL, REG_SZ, (PBYTE)pszRHS, sizeof(TCHAR) * (1+lstrlen(pszRHS)));
-      RegCloseKey (hk);
-      }
-}
-
index 7b65a57..831fd31 100644 (file)
@@ -33,6 +33,7 @@ enum DDDACTION  { DDD_ADD, DDD_REMOVE };
  * PROTOTYPES _________________________________________________________________
  *
  */
+extern void GetNetbiosName(LPTSTR pszName, int type);
 
 void AutoMap_OnInitDialog (HWND hDlg);
 void AutoMap_OnAdd (HWND hDlg);
@@ -449,7 +450,13 @@ void AutoMapEdit_OnInitDialog (HWND hDlg)
    SendMessage (hCombo, CB_SETCURSEL, iItemSel, 0);
 
    TCHAR szMapping[ MAX_PATH ];
+#ifdef NOLANA
    AdjustAfsPath (szMapping, ((pMap->szMapping[0]) ? pMap->szMapping : cm_slash_mount_root), TRUE, FALSE);
+#else
+    memset(szMapping, '\0', sizeof(szMapping));
+    szMapping[0] = '\\';
+    GetNetbiosName(&szMapping[1], 0);
+#endif
    SetDlgItemText (hDlg, IDC_PATH, szMapping);
    SetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount);
 
@@ -477,12 +484,25 @@ void AutoMapEdit_OnOK (HWND hDlg)
       return;
       }
 
-   if ( (lstrncmpi (pMap->szMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
-        (lstrncmpi (pMap->szMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
+#ifdef NOLANA
+    if ( (lstrncmpi (pMap->szMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
+         (lstrncmpi (pMap->szMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
+    {
+        Message (MB_ICONHAND, GetErrorTitle(), IDS_BADMAP_DESC);
+        return;
+    }
+#else
+   TCHAR szName[MAX_PATH];
+   memset(szName, '\0', sizeof(szName));
+   szName[0] = '\\';
+   GetNetbiosName(&szName[1], 0);
+
+   if ( lstrncmpi (pMap->szMapping, szName, lstrlen(szName) ))
       {
       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADMAP_DESC);
       return;
       }
+#endif
 
    // First get a proper submount
    if (pMap->szSubmount[0]) {
diff --git a/src/WINNT/client_config/dlg_binding.cpp b/src/WINNT/client_config/dlg_binding.cpp
new file mode 100644 (file)
index 0000000..91aafd2
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+extern "C" {
+#include <afs/param.h>
+#include <afs/stds.h>
+}
+#include <stdio.h>
+#include "afs_config.h"
+#include "getlana.h"
+
+
+/*
+ * DEFINITIONS ________________________________________________________________
+ *
+ */
+
+
+// Our dialog data
+static BOOL fFirstTime = TRUE;
+int nLanAdapter;
+LANAINFO* lanainfo = NULL;
+
+int GetAdapterNumber(TCHAR*);
+
+/*
+ * PROTOTYPES _________________________________________________________________
+ *
+ */
+
+void Binding_OnInitDialog (HWND hDlg);
+void Binding_OnOK(HWND hDlg);
+void Binding_OnCancel(HWND hDlg);
+BOOL Binding_OnApply();
+
+BOOL isGateway = FALSE;
+/*
+ * ROUTINES ___________________________________________________________________
+ *
+ */
+
+BOOL CALLBACK Binding_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
+{
+   switch (msg)
+      {
+      case WM_INITDIALOG:
+         Binding_OnInitDialog (hDlg);
+         break;
+
+      case WM_CTLCOLORSTATIC:
+         if ((HWND)lp == GetDlgItem (hDlg, IDC_CHUNK_SIZE))
+            {
+            if (IsWindowEnabled ((HWND)lp))
+               {
+               static HBRUSH hbrStatic = CreateSolidBrush (GetSysColor (COLOR_WINDOW));
+               SetTextColor ((HDC)wp, GetSysColor (COLOR_WINDOWTEXT));
+               SetBkColor ((HDC)wp, GetSysColor (COLOR_WINDOW));
+               return (BOOL)hbrStatic;
+               }
+            }
+         break;
+
+      case WM_COMMAND:
+         switch (LOWORD(wp))
+         {
+            case IDHELP:
+               Binding_DlgProc (hDlg, WM_HELP, 0, 0);
+               break;
+
+            case IDOK:
+                Binding_OnOK(hDlg);
+                break;
+                
+            case IDCANCEL:
+                Binding_OnCancel(hDlg);
+                break;
+                             case IDC_DEFAULTNIC:
+                if (HIWORD(wp) == BN_CLICKED)
+                {
+                  TCHAR name[MAX_PATH];
+                  memset(name, 0, sizeof(name));
+                                         if (IsDlgButtonChecked(hDlg,IDC_DEFAULTNIC))
+                                                 nLanAdapter=-1;
+                                         else
+                  {
+                    HWND hwndCombo = GetDlgItem(hDlg, IDC_NICSELECTION);
+                    if (SendMessage(hwndCombo, CB_GETCURSEL, 0, 0) == CB_ERR)
+                      SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
+
+                    TCHAR selected[MAX_PATH];
+                    memset(selected, 0, sizeof(selected));
+                    SendDlgItemMessage(hDlg, IDC_NICSELECTION, 
+                          WM_GETTEXT, sizeof(selected), 
+                          (LPARAM) selected); 
+
+                    if (_tcslen(selected) <= 0)
+                  
+                      nLanAdapter = -1;
+                    else
+                      nLanAdapter = GetAdapterNumber(selected);
+                  }
+                                   
+                  GetAfsName(nLanAdapter, isGateway, name);
+                  SetDlgItemText (hDlg, IDC_BINDING_MESSAGE, name);
+                                         EnableWindow(GetDlgItem(hDlg,IDC_NICSELECTION),(nLanAdapter!=-1));
+                  break;
+                }
+            case IDC_NICSELECTION:
+              if (HIWORD(wp) == CBN_SELCHANGE)
+              {
+                TCHAR name[MAX_PATH];
+                TCHAR selected[MAX_PATH];
+                memset(name, 0, sizeof(name));
+    &nbs