]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-unicode-20080527
authorAsanka Herath <asanka@secure-endpoints.com>
Thu, 26 Jun 2008 14:00:08 +0000 (14:00 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 26 Jun 2008 14:00:08 +0000 (14:00 +0000)
LICENSE MIT

An incremental commit.  This patch adds support for normalization of Unicode
but we have concluded that the normalization rules are incorrect.  Normalized
strings should not be written to the file server or returned to the application.

(cherry picked from commit c5911d25f8772aa1bb9b28a6cd58b8b781b479c1)

37 files changed:
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_flushvol.c
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/afslogon.c
src/WINNT/afsd/cm_btree.c
src/WINNT/afsd/cm_btree.h
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_dnlc.c
src/WINNT/afsd/cm_dns.c
src/WINNT/afsd/cm_freelance.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_nls.c [new file with mode: 0644]
src/WINNT/afsd/cm_nls.h [new file with mode: 0644]
src/WINNT/afsd/cm_utils.c
src/WINNT/afsd/cm_utils.h
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_vnodeops.h
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb3.c
src/WINNT/afsd/symlink.c
src/auth/NTMakefile
src/bozo/NTMakefile
src/bucoord/NTMakefile
src/budb/NTMakefile
src/butc/NTMakefile
src/kauth/NTMakefile
src/libafsauthent/NTMakefile
src/ptserver/NTMakefile
src/tbutc/NTMakefile
src/update/NTMakefile
src/vlserver/NTMakefile
src/volser/NTMakefile

index a5532b1af35cede29372b4fdd405d0b41998d819..672c3e0b80a74eae8ab05ae61cfcee7f6bce7d96 100644 (file)
@@ -65,6 +65,7 @@ INCFILES =\
        $(INCFILEDIR)\cm_freelance.h \
         $(INCFILEDIR)\cm_memmap.h \
        $(INCFILEDIR)\cm_performance.h \
+        $(INCFILEDIR)\cm_nls.h \
         $(INCFILEDIR)\afsd_eventlog.h \
         $(INCFILEDIR)\afsd_eventmessages.h \
         $(INCFILEDIR)\afskfw.h \
@@ -74,7 +75,8 @@ IDLFILES =\
        afsrpc.h $(OUT)\afsrpc_c.obj
 
 CONFOBJS=$(OUT)\cm_config.obj \
-         $(OUT)\cm_dns.obj
+         $(OUT)\cm_dns.obj \
+         $(OUT)\cm_nls.obj
 
 $(CONFOBJS):
 
@@ -120,6 +122,7 @@ AFSDOBJS=\
        $(OUT)\cm_rpc.obj \
         $(OUT)\cm_memmap.obj \
         $(OUT)\cm_performance.obj \
+        $(OUT)\cm_nls.obj \
        $(OUT)\afsrpc_s.obj \
 !IFDEF OSICRASH
        $(OUT)\afsdcrash.obj \
@@ -134,7 +137,8 @@ $(AFSDOBJS):
 $(OUT)\cm_conn.obj: cm_conn.c
        $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
 
-FSOBJS=$(OUT)\fs.obj $(OUT)\fs_utils.obj
+FSOBJS=$(OUT)\fs.obj \
+       $(OUT)\fs_utils.obj
 
 CMDBGOBJS=$(OUT)\cmdebug.obj
 
@@ -225,7 +229,8 @@ LOGON_DLLFILE = $(DESTDIR)\root.client\usr\vice\etc\afslogon.dll
 LOGON_DLLOBJS =\
     $(OUT)\afslogon.obj \
     $(OUT)\logon_ad.obj \
-    $(OUT)\afslogon.res
+    $(OUT)\afslogon.res \
+    $(OUT)\cm_nls.obj
 
 LOGON_DLLLIBS =\
     $(DESTDIR)\lib\afsauthent.lib \
@@ -277,8 +282,9 @@ $(LOG95_DLLFILE): $(LOG95_DLLOBJS) $(LOG95_DLLLIBS)
 ############################################################################
 # Install target; primary makefile target
 
-install_objs: $(OUT)\cm_dns.obj $(OUT)\cm_config.obj $(LANAHELPERLIB) $(OUT)\afsicf.obj
+install_objs: $(OUT)\cm_dns.obj $(OUT)\cm_config.obj $(OUT)\cm_nls.obj $(LANAHELPERLIB) $(OUT)\afsicf.obj
      $(COPY) $(OUT)\cm_dns.obj $(DESTDIR)\lib
+     $(COPY) $(OUT)\cm_nls.obj $(DESTDIR)\lib
      $(COPY) $(OUT)\cm_config.obj $(DESTDIR)\lib
      $(COPY) $(OUT)\afsicf.obj $(DESTDIR)\lib
 
@@ -336,7 +342,8 @@ EXELIBS = \
        $(DESTDIR)\lib\afsrx.lib \
        $(DESTDIR)\lib\afslwp.lib \
        $(DESTDIR)\lib\libosi.lib \
-       $(DESTDIR)\lib\libafsconf.lib
+       $(DESTDIR)\lib\libafsconf.lib \
+        $(DESTDIR)\lib\cm_nls.obj
 
 EXELIBS2 = \
         $(DESTDIR)\lib\afsrpc.lib \
index 993d76e94340473bbc1a2202a102e2dd2a0aa494..43d7a1792eb8df9507dc5bd66712268d545a9515 100644 (file)
@@ -64,6 +64,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include "cm_memmap.h"
 #include "cm_freelance.h"
 #include "cm_performance.h"
+#include "cm_nls.h"
 #include "smb_ioctl.h"
 #include "afsd_init.h"
 #ifdef DJGPP
index 02300c007fea5982d964c8abbd7fb47835b1833b..640e9ecf2e70bb392509aa9df8daccb224a436e0 100644 (file)
@@ -152,7 +152,7 @@ afsd_ServicePerformFlushVolumes()
             {
                 // got one!
                 // but we don't want to flush '\\[...]afs\all'
-                if (_stricmp(lpnr->lpRemoteName, pszShareName) == 0)
+                if (cm_stricmp_utf8(lpnr->lpRemoteName, pszShareName) == 0)
                     continue;
                 ++dwTotalVols;
 
index 8be4a6844471ada228ee68962fb72f4ddbbdfb7d..d1aaaba0048599816a31d6f0e12939e246664b2a 100644 (file)
@@ -299,7 +299,7 @@ configureBackConnectionHostNames(void)
                     (pName - pHostNames < dwSize) && *pName ; 
                     pName += strlen(pName) + 1)
                {
-                   if ( !stricmp(pName, cm_NetbiosName) ) {
+                   if ( !cm_stricmp_utf8(pName, cm_NetbiosName) ) {
                        bNameFound = TRUE;
                        break;
                    }   
index 5a74a35ade0dbe67625219dfb08f64ad81400058..af03d500a3247eabc871d9af7da4588f39c92104 100644 (file)
@@ -370,7 +370,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     if(domain) {
         dwSize = MAX_COMPUTERNAME_LENGTH;
         if(GetComputerName(computerName, &dwSize)) {
-            if(!stricmp(computerName, domain)) {
+            if(!cm_stricmp_utf8(computerName, domain)) {
                 effDomain = "LOCALHOST";
                 opt->flags = LOGON_FLAG_LOCAL;
             }
@@ -977,7 +977,7 @@ DWORD APIENTRY NPLogonNotify(
                             }
                            p = opt.theseCells;
                            while ( *p ) {
-                                if ( stricmp(p, cell) ) {
+                                if ( cm_stricmp_utf8(p, cell) ) {
                                     SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
                                     code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
                                     SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
index 55f6f04528365d8df55f5372295c6f255c7d51e1..47f4198486f935d72f1661c733296497b1eebedf 100644 (file)
@@ -141,7 +141,7 @@ Tree *initBtree(unsigned int poolsz, unsigned int fanout, KeyCmp keyCmp)
 {
     Tree *B;
     keyT empty = {NULL};
-    dataT data = {0,0,0,0};
+    dataT data = {0,0,0,0,0,0,0};
 
     if (fanout > MAX_FANOUT)
         fanout = MAX_FANOUT;
@@ -1293,6 +1293,10 @@ cleanupNodePool(Tree *B)
                 free(getdatavalue(node).longname);
                 getdatavalue(node).longname = NULL;
             }
+            if ( getdatavalue(node).origname ) {
+                free(getdatavalue(node).origname);
+                getdatavalue(node).origname = NULL;
+            }
         } else { /* data node */
             for ( j=1; j<=getfanout(B); j++ ) {
                 if (getkey(node, j).name)
@@ -1557,12 +1561,91 @@ compareKeys(keyT key1, keyT key2, int flags)
 {
     int comp;
 
-    comp = stricmp(key1.name, key2.name);
+    comp = cm_stricmp_utf8(key1.name, key2.name);
     if (comp == 0 && (flags & EXACT_MATCH))
         comp = strcmp(key1.name, key2.name);
     return (comp < 0 ? -1 : (comp > 0 ? 1 : 0));
 }
 
+int
+cm_BPlusDirLookupOriginalName(cm_dirOp_t * op, char * entry,
+                              char ** originalNameRetp)
+{
+    int rc = EINVAL;
+    keyT key = {entry};
+    Nptr leafNode = NONODE;
+    LARGE_INTEGER start, end;
+    char * originalName = NULL;
+
+    if (op->scp->dirBplus == NULL || 
+        op->dataVersion != op->scp->dirDataVersion) {
+        rc = EINVAL;
+        goto done;
+    }
+
+    lock_AssertAny(&op->scp->dirlock);
+
+    QueryPerformanceCounter(&start);
+
+    leafNode = bplus_Lookup(op->scp->dirBplus, key);
+    if (leafNode != NONODE) {
+        int         slot;
+        Nptr        firstDataNode, dataNode, nextDataNode;
+        int         exact = 0;
+        int         count = 0;
+
+        /* Found a leaf that matches the key via a case-insensitive
+         * match.  There may be one or more data nodes that match.
+         * If we have an exact match, return that.
+         * If we have an ambiguous match, return an error.
+         * If we have only one inexact match, return that.
+         */
+        slot = getSlot(op->scp->dirBplus, leafNode);
+        if (slot <= BTERROR) {
+            op->scp->dirDataVersion = 0;
+            rc = (slot == BTERROR ? EINVAL : ENOENT);
+            goto done;
+        }
+        firstDataNode = getnode(leafNode, slot);
+
+        for ( dataNode = firstDataNode; dataNode; dataNode = nextDataNode) {
+            count++;
+            if (!comparekeys(op->scp->dirBplus)(key, getdatakey(dataNode), EXACT_MATCH) ) {
+                exact = 1;
+                break;
+            }
+            nextDataNode = getdatanext(dataNode);
+        }
+
+        if (exact) {
+            originalName = getdatavalue(dataNode).origname;
+            rc = 0;
+            bplus_lookup_hits++;
+        } else if (count == 1) {
+            originalName = getdatavalue(firstDataNode).origname;
+            rc = CM_ERROR_INEXACT_MATCH;
+            bplus_lookup_hits_inexact++;
+        } else {
+            rc = CM_ERROR_AMBIGUOUS_FILENAME;
+            bplus_lookup_ambiguous++;
+        } 
+    } else {
+        rc = ENOENT;
+        bplus_lookup_misses++;
+    }
+
+    if (originalName)
+        *originalNameRetp = strdup(originalName);
+
+    QueryPerformanceCounter(&end);
+
+    bplus_lookup_time += (end.QuadPart - start.QuadPart);
+
+  done:
+    return rc;
+
+}
+
 /* Look up a file name in directory.
 
    On entry:
@@ -1671,6 +1754,7 @@ long cm_BPlusDirCreateEntry(cm_dirOp_t * op, char *entry, cm_fid_t * cfid)
 
     cm_SetFid(&data.fid, cfid->cell, cfid->volume, cfid->vnode, cfid->unique);
     data.longname = NULL;
+    data.origname = NULL;
 
     QueryPerformanceCounter(&start);
     bplus_create_entry++;
@@ -1859,6 +1943,7 @@ int cm_BPlusDirFoo(struct cm_scache *scp, struct cm_dirEntry *dep,
     char  *normalized_name=NULL;
     cm_SetFid(&data.fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
     data.longname = NULL;
+    data.origname = NULL;
 
     normalized_len = cm_NormalizeUtf8String(dep->name, -1, NULL, 0);
     if (normalized_len)
@@ -1866,6 +1951,8 @@ int cm_BPlusDirFoo(struct cm_scache *scp, struct cm_dirEntry *dep,
     if (normalized_name) {
         cm_NormalizeUtf8String(dep->name, -1, normalized_name, normalized_len);
         key.name = normalized_name;
+        if (strcmp(normalized_name, dep->name))
+            data.origname = strdup(dep->name);
     } else {
         key.name = dep->name;
     }
@@ -1880,7 +1967,8 @@ int cm_BPlusDirFoo(struct cm_scache *scp, struct cm_dirEntry *dep,
         cm_Gen8Dot3NameInt(dep->name, &dfid, shortName, NULL);
 
         key.name = shortName;
-        data.longname = strdup(dep->name);
+        data.longname = strdup(key.name);
+        data.origname = NULL;
         insert(scp->dirBplus, key, data);
     }
 
index 695ee3339f212f5c5f7f672744fb6fed45cf822e..3e37191eb28b39b46be7a51fcbfe9ddee9fd6dfc 100644 (file)
@@ -55,6 +55,7 @@ typedef struct key {
 typedef struct dirdata {
     cm_fid_t    fid;
     char * longname;
+    char * origname;
 } dataT;
 
 typedef struct entry {
@@ -136,7 +137,9 @@ void        delete(Tree *B, keyT key);
 Nptr   lookup(Tree *B, keyT key);
 
 /******************* cache manager directory operations ***************/
+
 int  cm_BPlusDirLookup(cm_dirOp_t * op, char *entry, cm_fid_t * cfid);
+int  cm_BPlusDirLookupOriginalName(cm_dirOp_t * op, char * entry, char ** originalNameRetp);
 long cm_BPlusDirCreateEntry(cm_dirOp_t * op, char *entry, cm_fid_t * cfid);
 int  cm_BPlusDirDeleteEntry(cm_dirOp_t * op, char *entry);
 long cm_BPlusDirBuildTree(cm_scache_t *scp, cm_user_t *userp, cm_req_t* reqp);
index ead30d39bbf08d719bc2f73d4e05e4b6c74269db..59cbd23cedb38b852ea3b5c27746780935eaefc1 100644 (file)
@@ -151,7 +151,7 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
 
     lock_ObtainRead(&cm_cellLock);
     for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
-        if (stricmp(namep, cp->name) == 0) {
+        if (cm_stricmp_utf8(namep, cp->name) == 0) {
             strcpy(fullname, cp->name);
             break;
         }
@@ -178,7 +178,7 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
          * to the list so check again while holding the write lock 
          */
         for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
-            if (stricmp(namep, cp->name) == 0) {
+            if (cm_stricmp_utf8(namep, cp->name) == 0) {
                 strcpy(fullname, cp->name);
                 break;
             }
@@ -247,7 +247,7 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
          */
         hash = CM_CELL_NAME_HASH(fullname);
         for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) {
-            if (stricmp(fullname, cp2->name) == 0) {
+            if (cm_stricmp_utf8(fullname, cp2->name) == 0) {
                 break;
             }
         }   
index 8812dab29857ab947290c80657eb66a90c163a3f..4a885a2fcc4eb3d18f69e5e5f72913a9a7dac8ca 100644 (file)
@@ -93,11 +93,11 @@ IsWindowsModule(const char * name)
     p = strrchr(name, '.');
     if (p) {
        if (i == 1 && 
-           (!stricmp(p,".dll") ||
-            !stricmp(p,".exe") ||
-            !stricmp(p,".ini") ||
-            !stricmp(p,".db") ||
-            !stricmp(p,".drv")))
+           (!cm_stricmp_utf8N(p,".dll") ||
+            !cm_stricmp_utf8N(p,".exe") ||
+            !cm_stricmp_utf8N(p,".ini") ||
+            !cm_stricmp_utf8N(p,".db") ||
+            !cm_stricmp_utf8N(p,".drv")))
            return 1;
     }
     return 0;
@@ -203,8 +203,7 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                         inRightCell, osi_LogSaveString(afsd_logp,lineBuffer));
 #endif
            }
-           else if (strnicmp(lineBuffer+1, cellNamep,
-                              strlen(cellNamep)) == 0) {
+           else if (cm_stricmp_utf8(lineBuffer+1, cellNamep) == 0) {
                /* partial match */
                if (partial) {  /* ambiguous */
                    fclose(tfilep);
index d441d760acc512da1c5ba41fe94ccebc8c7fa696..6ae8673092180561cdd791e8a1371fe42e007ba9 100644 (file)
@@ -574,6 +574,7 @@ cm_DirMakeDir(cm_dirOp_t * op, cm_fid_t * me, cm_fid_t * parent)
     return rc;
 }
 
+
 /* Look up a file name in directory.
 
    On entry:
index abcc18ca2ac1ded8185a597599c6a5bccfb2cbda..acb9029d9b90ed3a84f81c28a9e40b2dfa30569c 100644 (file)
@@ -232,7 +232,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
 
            if ( sp->caseFold )         /* case insensitive */
            {
-            match = cm_stricmp(tnc->name, aname);
+            match = cm_stricmp_utf8(tnc->name, aname);
             if ( !match )      /* something matches */
             {
                 tvc = tnc->vp;
index 0e92606933591e42d28413e5eb8e0e928db98623..cc390e51211bd4e3c6ac079921fe54f3b1f8969b 100644 (file)
@@ -17,6 +17,7 @@
 #endif
 #include "cm_dns_private.h"
 #include "cm_dns.h"
+#include "cm_nls.h"
 #include <lwp.h>
 #include <afs/afsint.h>
 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
@@ -708,7 +709,7 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
     char query[1024];
 
 #ifdef AFS_FREELANCE_CLIENT
-    if ( stricmp(cellName, "Freelance.Local.Root") == 0 )
+    if ( cm_stricmp_utf8N(cellName, "Freelance.Local.Root") == 0 )
         return -1;
 #endif /* AFS_FREELANCE_CLIENT */
 
@@ -749,7 +750,7 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
             if(pDnsIter->wType == DNS_TYPE_A)
                 /* check if its for one of the volservers */
                 for (i=0;i<*numServers;i++)
-                    if(stricmp(pDnsIter->pName, cellHostNames[i]) == 0)
+                    if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
                         cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
         }       
 
@@ -760,14 +761,14 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
                 if (DnsQuery_A(cellHostNames[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(cellHostNames[i], pDnsVolIter->pName)==0) {
+                        if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
                             cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                             break;
                         }
                         /* if we get a CNAME, look for a corresponding A record */
-                        if (pDnsVolIter->wType == DNS_TYPE_CNAME && stricmp(cellHostNames[i], pDnsVolIter->pName)==0) {
+                        if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[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) {
+                                if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                     cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                     break;
                                 }
index 436e16d6a23765d6522d7f9ab39bffc5e9044538..f5c5a2c2415e4475deed19ced256fe473371d802 100644 (file)
@@ -874,7 +874,7 @@ long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
             memcpy(shortname, line, cp-line);
             shortname[cp-line]=0;
 
-            if (!stricmp(shortname, filename)) {
+            if (!cm_stricmp_utf8(shortname, filename)) {
                 found = 1;
                 break;
             }
@@ -957,7 +957,7 @@ long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
             memcpy(shortname, line, cp-line);
             shortname[cp-line]=0;
 
-            if (!stricmp(shortname, filename)) {
+            if (!cm_stricmp_utf8(shortname, filename)) {
                 found = 1;
                 break;
             }
@@ -1237,11 +1237,11 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     fullname[0] = '\0';
     if (filename[0] == '.') {
         cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
-        if (stricmp(&filename[1],fullname) == 0)
+        if (cm_stricmp_utf8(&filename[1],fullname) == 0)
             return CM_ERROR_EXISTS;
     } else {
         cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
-        if (stricmp(filename,fullname) == 0)
+        if (cm_stricmp_utf8(filename,fullname) == 0)
             return CM_ERROR_EXISTS;
     }
 
index c203104a4e5530c87baf5f03f591b0a6ac546ee9..2dd945de2b45d2f11ec295e9f6a167810de10cd1 100644 (file)
@@ -46,6 +46,8 @@
 #include <winioctl.h>
 #include <rx\rx.h>
 
+#include "cm_btree.h"
+
 #ifdef _DEBUG
 #include <crtdbg.h>
 #endif
@@ -593,6 +595,10 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
         free(inpathp);
     inpathp = NULL;             /* We don't need this from this point on */
 
+    if (free_path)
+        free(inpathp);
+    inpathp = NULL;             /* We don't need this from this point on */
+
     if (tbuffer[0] == tbuffer[1] &&
         tbuffer[1] == '\\' && 
         !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName))) 
@@ -1413,7 +1419,9 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_scache_t *dscp;
     cm_scache_t *scp;
     char *cp;
+    char *originalName = NULL;
     cm_req_t req;
+    cm_dirOp_t dirop;
 
     cm_InitReq(&req);
 
@@ -1443,23 +1451,49 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
     /* time to make the RPC, so drop the lock */
     lock_ReleaseWrite(&scp->rw);
 
+#ifdef USE_BPLUS
+    code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop);
+    if (code == 0) {
+        code = cm_BPlusDirLookupOriginalName(&dirop, cp, &originalName);
+        /* The cm_Dir* functions can't be used to lookup the
+           originalName.  Those functions only know of the original
+           name. */
+        cm_EndDirOp(&dirop);
+    }
+#endif
+
+    /* If this name doesn't have a non-normalized name associated with
+       it, we assume that what we had is what is actually present on
+       the file server. */
+
+    if (originalName == NULL) {
+        originalName = cp;
+    }
+
+    /* cp is a normalized name.  originalName is the actual name we
+       saw on the fileserver. */
 #ifdef AFS_FREELANCE_CLIENT
     if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
         /* we are adding the mount point to the root dir., so call
          * the freelance code to do the add. */
         osi_Log0(afsd_logp,"IoctlDeleteMountPoint from Freelance root dir");
-        code = cm_FreelanceRemoveMount(cp);
+        code = cm_FreelanceRemoveMount(originalName);
     } else 
 #endif
     {
         /* easier to do it this way */
-        code = cm_Unlink(dscp, cp, userp, &req);
+        code = cm_Unlink(dscp, originalName, cp, userp, &req);
     }
     if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
         smb_NotifyChange(FILE_ACTION_REMOVED,
                           FILE_NOTIFY_CHANGE_DIR_NAME,
                           dscp, cp, NULL, TRUE);
 
+    if (originalName != NULL && originalName != cp) {
+        free(originalName);
+        originalName = NULL;
+    }
+
     lock_ObtainWrite(&scp->rw);
   done1:
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -2307,7 +2341,9 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_scache_t *dscp;
     cm_scache_t *scp;
     char *cp;
+    char * originalName = NULL;
     cm_req_t req;
+    cm_dirOp_t dirop;
 
     cm_InitReq(&req);
 
@@ -2339,17 +2375,39 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     /* time to make the RPC, so drop the lock */
     lock_ReleaseWrite(&scp->rw);
         
+#ifdef USE_BPLUS
+    code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop);
+    if (code == 0) {
+        code = cm_BPlusDirLookupOriginalName(&dirop, cp, &originalName);
+        /* cm_Dir*() functions can't be used to lookup the original
+           name since those functions only know of the original
+           name. */
+        cm_EndDirOp(&dirop);
+    }
+#endif
+
+    /* If this name doesn't have a non-normalized name associated with
+       it, we assume that what we had is what is actually present on
+       the file server. */
+
+    if (originalName == NULL)
+        originalName = cp;
+
+    /* cp is a normalized name.  originalName is the actual name we
+       saw on the fileserver. */
+
+
 #ifdef AFS_FREELANCE_CLIENT
     if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
         /* we are adding the mount point to the root dir., so call
          * the freelance code to do the add. */
         osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
-        code = cm_FreelanceRemoveSymlink(cp);
+        code = cm_FreelanceRemoveSymlink(originalName);
     } else 
 #endif
     {
         /* easier to do it this way */
-        code = cm_Unlink(dscp, cp, userp, &req);
+        code = cm_Unlink(dscp, originalName, cp, userp, &req);
     }
     if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
         smb_NotifyChange(FILE_ACTION_REMOVED,
@@ -2357,6 +2415,11 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
                           | FILE_NOTIFY_CHANGE_DIR_NAME,
                           dscp, cp, NULL, TRUE);
 
+    if (originalName != NULL && originalName != cp) {
+        free(originalName);
+        originalName = NULL;
+    }
+
     lock_ObtainWrite(&scp->rw);
   done1:
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -2428,7 +2491,7 @@ long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
        if (*p == '@')
            r = p;
     }
-    if (r && !stricmp(r+1,ucellp->cellp->name))
+    if (r && !cm_stricmp_utf8(r+1,ucellp->cellp->name))
        *r = '\0';
 
     code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
diff --git a/src/WINNT/afsd/cm_nls.c b/src/WINNT/afsd/cm_nls.c
new file mode 100644 (file)
index 0000000..cdeb9e3
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2008 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <strsafe.h>
+#include <errno.h>
+
+#define DEBUG_UNICODE
+
+/* This is part of the Microsoft Internationalized Domain Name
+   Mitigation APIs. */
+#include <normalization.h>
+
+int
+(WINAPI *pNormalizeString)( __in NORM_FORM NormForm,
+                            __in_ecount(cwSrcLength) LPCWSTR lpSrcString,
+                            __in int cwSrcLength,
+                            __out_ecount(cwDstLength) LPWSTR lpDstString,
+                            __in int cwDstLength ) = NULL;
+
+BOOL
+(WINAPI *pIsNormalizedString)( __in NORM_FORM NormForm,
+                               __in_ecount(cwLength) LPCWSTR lpString,
+                               __in int cwLength ) = NULL;
+
+
+#define NLSDLLNAME "Normaliz.dll"
+#define NLSMAXCCH  1024
+#define NLSERRCCH  8
+
+#define AFS_NORM_FORM NormalizationC
+
+long cm_InitNormalization(void)
+{
+    HMODULE h_Nls;
+
+    if (pNormalizeString != NULL)
+        return 0;
+
+    h_Nls = LoadLibrary(NLSDLLNAME);
+    if (h_Nls == INVALID_HANDLE_VALUE) {
+        return 1;
+    }
+
+    pNormalizeString = GetProcAddress(h_Nls, "NormalizeString");
+    pIsNormalizedString = GetProcAddress(h_Nls, "IsNormalizedString");
+
+    return (pNormalizeString && pIsNormalizedString);
+}
+
+/* \brief Normalize a UTF-16 string.
+
+   If the supplied destination buffer is insufficient or NULL, then a
+   new buffer will be allocated to hold the normalized string.
+
+   \param[in] src : Source UTF-16 string.  Length is specified in
+       cch_src.
+
+   \param[in] cch_src : The character count in cch_src is assumed to
+       be tight and include the terminating NULL character if there is
+       one.  If the NULL is absent, the resulting string will not be
+       NULL terminated.
+
+   \param[out] ext_dest : The destination buffer.  Can be NULL, in
+       which case *pcch_dest MUST be 0.
+
+   \param[in,out] pcch_dest : On entry *pcch_dest contains a count of
+       characters in the destination buffer.  On exit, it will contain
+       a count of characters that were copied to the destination
+       buffer.
+
+   Returns a pointer to the buffer containing the normalized string or
+   NULL if the call was unsuccessful.  If the returned destination
+   buffer is different from the supplied buffer and non-NULL, it
+   should be freed using free().
+*/
+static wchar_t * 
+NormalizeUtf16String(const wchar_t * src, int cch_src, wchar_t * ext_dest, int *pcch_dest)
+{
+    if ((pIsNormalizedString && (*pIsNormalizedString)(AFS_NORM_FORM, src, cch_src)) ||
+        (!pNormalizeString)) {
+
+        if (ext_dest == NULL || *pcch_dest < cch_src) {
+            ext_dest = malloc(cch_src * sizeof(wchar_t));
+            *pcch_dest = cch_src;
+        }
+
+        /* No need to or unable to normalize.  Just copy the string.
+           Note that the string is not necessarily NULL terminated. */
+
+        if (ext_dest) {
+            memcpy(ext_dest, src, cch_src * sizeof(wchar_t));
+            *pcch_dest = cch_src;
+        } else {
+            *pcch_dest = 0;
+        }
+        return ext_dest;
+
+    } else {
+
+        int rv;
+        DWORD gle;
+        int tries = 10;
+        wchar_t * dest;
+        int cch_dest = *pcch_dest;
+
+        dest = ext_dest;
+
+        while (tries-- > 0) {
+
+            rv = (*pNormalizeString)(AFS_NORM_FORM, src, cch_src, dest, cch_dest);
+
+            if (rv <= 0 && (gle = GetLastError()) != ERROR_SUCCESS) {
+                if (gle == ERROR_INSUFFICIENT_BUFFER) {
+
+                    /* The buffer wasn't big enough.  We are going to
+                       try allocating one. */
+
+                    cch_dest = (-rv) + NLSERRCCH;
+                    goto cont;
+
+                } else {
+                    /* Something else is wrong */
+                    break;
+                }
+
+            } else if (rv < 0) { /* rv < 0 && gle == ERROR_SUCCESS */
+
+                /* Technically not one of the expected outcomes */
+                break;
+
+            } else {            /* rv > 0 || (rv == 0 && gle == ERROR_SUCCESS) */
+
+                /* Possibly succeeded */
+
+                if (rv == 0) { /* Succeeded and the return string is empty */
+                    *pcch_dest = 0;
+                    return dest;
+                }
+
+                if (cch_dest == 0) {
+                    /* Nope.  We only calculated the required size of the buffer */
+
+                    cch_dest = rv + NLSERRCCH;
+                    goto cont;
+                }
+
+                *pcch_dest = rv;
+
+                /* Success! */
+                return dest;
+            }
+
+        cont:
+            if (dest != ext_dest && dest)
+                free(dest);
+            dest = malloc(cch_dest * sizeof(wchar_t));
+        }
+
+        /* Failed */
+
+        if (dest != ext_dest && dest)
+            free(dest);
+
+        *pcch_dest = 0;
+        return NULL;
+    }
+}
+
+/* \brief Normalize a UTF-16 string into a UTF-8 string.
+
+   \param[in] src : Source string.
+
+   \param[in] cch_src : Count of characters in src. If the count includes the
+       NULL terminator, then the resulting string will be NULL
+       terminated.  If it is -1, then src is assumed to be NULL
+       terminated.
+
+   \param[out] adest : Destination buffer.
+
+   \param[in] cch_adest : Number of characters in the destination buffer.
+
+   Returns the number of characters stored into cch_adest. This will
+   include the terminating NULL if cch_src included the terminating
+   NULL or was -1.  If this is 0, then the operation was unsuccessful.
+ */
+long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src,
+                                   char * adest, int cch_adest)
+{
+    if (cch_src < 0) {
+        size_t cch;
+
+        if (FAILED(StringCchLengthW(src, NLSMAXCCH, &cch)))
+            return E2BIG;
+
+        cch_src = cch+1;
+    }
+
+    {
+        wchar_t nbuf[NLSMAXCCH];
+        wchar_t * normalized;
+        int cch_norm = NLSMAXCCH;
+
+        normalized = NormalizeUtf16String(src, cch_src, nbuf, &cch_norm);
+        if (normalized) {
+            cch_adest = WideCharToMultiByte(CP_UTF8, 0, normalized, cch_norm,
+                                            adest, cch_adest, NULL, 0);
+
+            if (normalized != nbuf && normalized)
+                free(normalized);
+
+            return cch_adest;
+
+        } else {
+
+            return 0;
+
+        }
+    }
+}
+
+#define ESCVAL 0x1000
+#define Esc(c) (ESCVAL + (short)(c))
+#define IS_ESCAPED(c) (((c) & ESCVAL) == ESCVAL)
+
+/* \brief Character sanitization map for CP-1252
+
+   The following map indicates which characters should be escaped in
+   the CP-1252 character map.  Characters that are documented as
+   illegal characters in a file name are marked as escaped.  Escaped
+   characters are marked using the ::Esc macro defined above.  The
+   following exceptions apply:
+
+   - Path delimeters '\\' and '/' are NOT escaped because the
+     sanitization map applies to paths.  While those characters are
+     illegal in filenames, they are legal in paths.
+
+   - Wildcard characters '*' and '?' ARE escaped.  The document
+     referred below does not specify these characters as invalid.
+     Since no other escape mechanism exists, names containing
+     wildcards are indistinguishable from actual wildcards used in SMB
+     requests.
+
+   - Reserved names are not and cannot be represented in this map.
+     Reserved names are :
+
+     CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7,
+     COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9,
+     CLOCK$
+
+   - Characters 0x80, 0x81, 0x8d, 0x8e, 0x8f, 0x90, 0x9d, 0x9e, 0x9f
+     are also escaped because they are unused in CP-1252 and hence
+     cannot be convered to a Unicode string.
+
+     Reserved names with extensions are also invalid. (i.e. NUL.txt)
+
+   \note The only bit we are actually interested in from the following
+     table is the ESCVAL bit.  However, the characters themselves are
+     included for ease of maintenance.
+
+   \see "Naming a File" topic in the Windows SDK.
+ */
+static const short sanitized_escapes_1252[] = {
+    Esc(0x00),Esc(0x01),Esc(0x02),Esc(0x03),Esc(0x04),Esc(0x05),Esc(0x06),Esc(0x07),
+    Esc(0x08),Esc(0x09),Esc(0x0a),Esc(0x0b),Esc(0x0c),Esc(0x0d),Esc(0x0e),Esc(0x0f),
+    Esc(0x10),Esc(0x11),Esc(0x12),Esc(0x13),Esc(0x14),Esc(0x15),Esc(0x16),Esc(0x17),
+    Esc(0x18),Esc(0x19),Esc(0x1a),Esc(0x1b),Esc(0x1c),Esc(0x1d),Esc(0x1e),Esc(0x1f),
+    ' ','!',Esc('"'),'#','$','%','&','\'','(',')',Esc('*'),'+',',','-','.','/',
+    '0','1','2','3','4','5','6','7','8','9',Esc(':'),';',Esc('<'),'=',Esc('>'),Esc('?'),
+    '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
+    'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
+    '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
+    'p','q','r','s','t','u','v','w','x','y','z','{',Esc('|'),'}','~',Esc(0x7f),
+    Esc(0x80),Esc(0x81),0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,Esc(0x8d),Esc(0x8e),Esc(0x8f),
+    Esc(0x90),0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,Esc(0x9d),Esc(0x9e),0x9f,
+    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
+    0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
+    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
+    0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
+    0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
+    0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+};
+
+static int sanitize_bytestring(const char * src, int cch_src,
+                                char * odest, int cch_dest)
+{
+    char * dest = odest;
+    while (cch_src > 0 && *src && cch_dest > 0) {
+
+        unsigned short rc;
+
+        rc = sanitized_escapes_1252[*src];
+        if (IS_ESCAPED(rc)) {
+            static const char hex[] = 
+                {'0','1','2','3','4','5','6','7',
+                 '8','9','a','b','c','d','e','f'};
+
+            if (cch_dest < 3) {
+                *dest++ = '\0';
+                return 0;
+            }
+
+            *dest++ = '%';
+            *dest++ = hex[(((int)*src) >> 4) & 0x0f];
+            *dest++ = hex[(((int)*src) & 0x0f)];
+            cch_dest -= 3;
+
+        } else {
+            *dest++ = *src;
+            cch_dest--;
+        }
+
+        cch_src--;
+        src++;
+    }
+
+    if (cch_src > 0 && cch_dest > 0) {
+        *dest++ = '\0';
+    }
+
+    return (int)(dest - odest);
+}
+
+#undef Esc
+#undef IS_ESCAPED
+#undef ESCVAL
+
+/* \brief Normalize a UTF-8 string.
+
+   \param[in] src String to normalize.
+
+   \param[in] cch_src : Count of characters in src.  If this value is
+       -1, then src is assumed to be NULL terminated.  The translated
+       string will be NULL terminated only if this is -1 or the count
+       includes the terminating NULL.
+
+   \param[out] adest : Destination string.  Only considered valid if
+       \a cch_adest is non-zero.
+
+   \param[in] cch_adest : Number of characters in the destination
+       string.  If this is zero, then the return value is the number
+       of bytes required.
+
+   \return If \a cch_adest is non-zero, then the return value is the
+       number of bytes stored into adest.  If \a cch_adest is zero,
+       then the return value is the number of bytes required.  In both
+       cases, the return value is 0 if the call was unsuccessful.
+ */
+long cm_NormalizeUtf8String(const char * src, int cch_src,
+                            char * adest, int cch_adest)
+{
+    wchar_t wsrcbuf[NLSMAXCCH];
+    wchar_t *wnorm;
+    int cch;
+    int cch_norm;
+
+    /* Get some edge cases out first, so we don't have to worry about
+       cch_src being 0 etc. */
+    if (cch_src == 0) {
+        return 0;
+    } else if (*src == '\0') {
+        if (cch_adest >= 1)
+            *adest = '\0';
+        return 1;
+    }
+
+    if (cch_src == -1) {
+        cch_src = strlen(src) + 1;
+    }
+
+    cch = MultiByteToWideChar(CP_UTF8, 0, src,
+                              cch_src * sizeof(char), wsrcbuf, NLSMAXCCH);
+
+    if (cch == 0) {
+        if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
+            char sanitized[NLSMAXCCH];
+            int cch_sanitized;
+
+            /* If src doesn't have a unicode translation, then it
+               wasn't valid UTF-8.  In this case, we assume that src
+               is CP-1252 and then try to convert again.  But before
+               that, we use a translation table to "sanitize" the
+               input. */
+
+            cch_sanitized = sanitize_bytestring(src, cch_src, sanitized,
+                                                sizeof(sanitized)/sizeof(char));
+
+            if (cch_sanitized == 0) {
+#ifdef DEBUG_UNICODE
+                DebugBreak();
+#endif
+                return 0;
+            }
+
+            cch = MultiByteToWideChar(1252, 0, sanitized,
+                                      cch_sanitized * sizeof(char), wsrcbuf, NLSMAXCCH);
+            if (cch == 0) {
+                /* Well, that didn't work either.  Something is very wrong. */
+#ifdef DEBUG_UNICODE
+                DebugBreak();
+#endif
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    cch_norm = 0;
+    wnorm = NormalizeUtf16String(wsrcbuf, cch, NULL, &cch_norm);
+    if (wnorm == NULL) {
+#ifdef DEBUG_UNICODE
+        DebugBreak();
+#endif
+        return 0;
+    }
+
+    cch = WideCharToMultiByte(CP_UTF8, 0, wnorm,
+                              cch_norm, adest, cch_adest * sizeof(char),
+                              NULL, FALSE);
+
+    if (wnorm)
+        free(wnorm);
+
+    return cch;
+}
+
+/*! \brief Case insensitive comparison with specific length
+
+  \param[in] str1 First string to compare.  Assumed to be encoded in UTF-8.
+
+  \param[in] str2 Second string to compare.  Assumed to be encoded in UTF-8.
+
+  \param[in] n Max byte count.
+
+ */
+int cm_strnicmp_utf8(const char * str1, const char * str2, int n)
+{
+    wchar_t wstr1[NLSMAXCCH];
+    int len1;
+    int len2;
+    wchar_t wstr2[NLSMAXCCH];
+    int rv;
+
+    /* first check for NULL pointers */
+    if (str1 == NULL) {
+        if (str2 == NULL)
+            return 0;
+        else
+            return -1;
+    } else if (str2 == NULL) {
+        return 1;
+    }
+
+    len1 = MultiByteToWideChar(CP_UTF8, 0, str1, n, wstr1, NLSMAXCCH);
+    if (len1 == 0) {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        wstr1[0] = L'\0';
+    }
+
+    len2 = MultiByteToWideChar(CP_UTF8, 0, str2, n, wstr2, NLSMAXCCH);
+    if (len2 == 0) {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        wstr2[0] = L'\0';
+    }
+
+    rv = CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wstr1, len1, wstr2, len2);
+    if (rv > 0)
+        return (rv - 2);
+    else {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        return 0;
+    }
+}
+
+int cm_stricmp_utf8(const char * str1, const char * str2)
+{
+    wchar_t wstr1[NLSMAXCCH];
+    int len1;
+    int len2;
+    wchar_t wstr2[NLSMAXCCH];
+    int rv;
+
+    /* first check for NULL pointers */
+    if (str1 == NULL) {
+        if (str2 == NULL)
+            return 0;
+        else
+            return -1;
+    } else if (str2 == NULL) {
+        return 1;
+    }
+
+    len1 = MultiByteToWideChar(CP_UTF8, 0, str1, -1, wstr1, NLSMAXCCH);
+    if (len1 == 0) {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        wstr1[0] = L'\0';
+    }
+
+    len2 = MultiByteToWideChar(CP_UTF8, 0, str2, -1, wstr2, NLSMAXCCH);
+    if (len2 == 0) {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        wstr2[0] = L'\0';
+    }
+
+    rv = CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wstr1, len1, wstr2, len2);
+    if (rv > 0)
+        return (rv - 2);
+    else {
+#ifdef DEBUG
+        DebugBreak();
+#endif
+        return 0;
+    }
+}
+
+wchar_t * strupr_utf16(wchar_t * wstr, size_t cbstr)
+{
+    wchar_t wstrd[NLSMAXCCH];
+    int len;
+
+    len = cbstr / sizeof(wchar_t);
+    len = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, wstr, len, wstrd, NLSMAXCCH);
+    StringCbCopyW(wstr, cbstr, wstrd);
+
+    return wstr;
+}
+
+char * strupr_utf8(char * str, size_t cbstr)
+{
+    wchar_t wstr[NLSMAXCCH];
+    wchar_t wstrd[NLSMAXCCH];
+    int len;
+    int r;
+
+    len = MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, NLSMAXCCH);
+    if (len == 0)
+        return str;
+
+    len = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, wstr, len, wstrd, NLSMAXCCH);
+
+    len = WideCharToMultiByte(CP_UTF8, 0, wstrd, -1, str, cbstr, NULL, FALSE);
+
+    return str;
+}
+
+char * char_next_utf8(const char * c)
+{
+#define CH (*((const unsigned char *)c))
+
+    if ((CH & 0x80) == 0)
+        return (char *) c+1;
+    else {
+        switch (CH & 0xf0) {
+        case 0xc0:
+        case 0xd0:
+            return (char *) c+2;
+
+        case 0xe0:
+            return (char *) c+3;
+
+        case 0xf0:
+            return (char *) c+4;
+
+        default:
+            return (char *) c+1;
+        }
+    }
+#undef CH
+}
+
+
+char * char_prev_utf8(const char * c)
+{
+#define CH (*((const unsigned char *)c))
+
+    c--;
+
+    if ((CH & 0x80) == 0)
+        return (char *) c;
+    else
+        while ((CH & 0xc0) == 0x80)
+            (char *) c--;
+    return (char *) c;
+
+#undef CH
+}
diff --git a/src/WINNT/afsd/cm_nls.h b/src/WINNT/afsd/cm_nls.h
new file mode 100644 (file)
index 0000000..ba7add3
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CM_NLS_H_ENV__
+#define __CM_NLS_H_ENV__
+
+extern long cm_InitNormalization(void);
+
+extern long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src,
+                                          char * adest, int cch_adest);
+
+extern long cm_NormalizeUtf8String(const char * src, int cch_src,
+                                   char * adest, int cch_adest);
+
+/* The cm_stricmp_utf8N function is identical to cm_stricmp_utf8
+   except it is used in instances where one of the strings is always
+   known to be ASCII. */
+extern int cm_stricmp_utf8N(const char * str1, const char * str2);
+#define cm_stricmp_utf8N cm_stricmp_utf8
+
+extern int cm_stricmp_utf8(const char * str1, const char * str2);
+
+/* The cm_strnicmp_utf8N function is identical to cm_strnicmp_utf8
+   except it is used in instances where one of the strings is always
+   known to be ASCII. */
+extern int cm_strnicmp_utf8N(const char * str1, const char * str2, int n);
+#define cm_strnicmp_utf8N cm_strnicmp_utf8
+
+extern int cm_strnicmp_utf8(const char * str1, const char * str2, int n);
+
+extern char * char_next_utf8(const char * c);
+
+extern char * char_prev_utf8(const char * c);
+
+extern char * strupr_utf8(char * str, size_t cbstr);
+
+#endif
index e0d300652b17fabb6e3ffb58edac5b9c957860ab..b86c999e226226e7dbd7535fd398b467e36a80ab 100644 (file)
@@ -365,275 +365,3 @@ void cm_FreeSpace(cm_space_t *tsp)
         lock_ReleaseWrite(&cm_utilsLock);
 }
 
-/* This is part of the Microsoft Internationalized Domain Name
-   Mitigation APIs. */
-#include <normalization.h>
-
-int
-(WINAPI *pNormalizeString)( __in NORM_FORM NormForm,
-                            __in_ecount(cwSrcLength) LPCWSTR lpSrcString,
-                            __in int cwSrcLength,
-                            __out_ecount(cwDstLength) LPWSTR lpDstString,
-                            __in int cwDstLength ) = NULL;
-
-BOOL
-(WINAPI *pIsNormalizedString)( __in NORM_FORM NormForm,
-                               __in_ecount(cwLength) LPCWSTR lpString,
-                               __in int cwLength ) = NULL;
-
-
-#define NLSDLLNAME "Normaliz.dll"
-#define NLSMAXCCH  1024
-#define NLSERRCCH  8
-
-#define AFS_NORM_FORM NormalizationC
-
-long cm_InitNormalization(void)
-{
-    HMODULE h_Nls;
-
-    if (pNormalizeString != NULL)
-        return 0;
-
-    h_Nls = LoadLibrary(NLSDLLNAME);
-    if (h_Nls == INVALID_HANDLE_VALUE) {
-        afsi_log("Can't load " NLSDLLNAME ": LastError=%d", GetLastError());
-        return 1;
-    }
-
-    pNormalizeString = GetProcAddress(h_Nls, "NormalizeString");
-    pIsNormalizedString = GetProcAddress(h_Nls, "IsNormalizedString");
-
-    return (pNormalizeString && pIsNormalizedString);
-}
-
-/* \brief Normalize a UTF-16 string.
-
-   If the supplied destination buffer is
-   insufficient or NULL, then a new buffer will be allocated to hold
-   the normalized string.
-
-   \param[in] src : Source UTF-16 string.  Length is specified in
-       cch_src.
-
-   \param[in] cch_src : The character count in cch_src is assumed to
-       be tight and include the terminating NULL character if there is
-       one.  If the NULL is absent, the resulting string will not be
-       NULL terminated.
-
-   \param[out] ext_dest : The destination buffer.  Can be NULL, in
-       which case *pcch_dest MUST be NULL.
-
-   \param[in,out] pcch_dest : On entry *pcch_dest contains a count of
-       characters in the destination buffer.  On exit, it will contain
-       a count of characters that were copied to the destination
-       buffer.
-
-   Returns a pointer to the buffer containing the normalized string or
-   NULL if the call was unsuccessful.  If the returned destination
-   buffer is different from the supplied buffer and non-NULL, it
-   should be freed using free().
-*/
-static wchar_t * 
-NormalizeUtf16String(const wchar_t * src, int cch_src, wchar_t * ext_dest, int *pcch_dest)
-{
-    if ((pIsNormalizedString && (*pIsNormalizedString)(AFS_NORM_FORM, src, cch_src)) ||
-        (!pNormalizeString)) {
-
-        /* No need to or unable to normalize.  Just copy the string */
-        if (SUCCEEDED(StringCchCopyNW(ext_dest, *pcch_dest, src, cch_src))) {
-            *pcch_dest = cch_src;
-            return ext_dest;
-        } else {
-            *pcch_dest = 0;
-            return NULL;
-        }
-    } else {
-
-        int rv;
-        DWORD gle;
-        int tries = 10;
-        wchar_t * dest;
-        int cch_dest = *pcch_dest;
-
-        dest = ext_dest;
-
-        while (tries-- > 0) {
-
-            rv = (*pNormalizeString)(AFS_NORM_FORM, src, cch_src, dest, cch_dest);
-
-            if (rv <= 0 && (gle = GetLastError()) != ERROR_SUCCESS) {
-#ifdef DEBUG
-                osi_Log1(afsd_logp, "NormalizeUtf16String error = %d", gle);
-#endif
-                if (gle == ERROR_INSUFFICIENT_BUFFER) {
-
-                    /* The buffer wasn't big enough.  We are going to
-                       try allocating one. */
-
-                    cch_dest = (-rv) + NLSERRCCH;
-                    goto cont;
-
-                } else {
-                    /* Something else is wrong */
-                    break;
-                }
-
-            } else if (rv < 0) { /* rv < 0 && gle == ERROR_SUCCESS */
-
-                /* Technically not one of the expected outcomes */
-                break;
-
-            } else {            /* rv > 0 || (rv == 0 && gle == ERROR_SUCCESS) */
-
-                /* Possibly succeeded */
-
-                if (rv == 0) { /* Succeeded and the return string is empty */
-                    *pcch_dest = 0;
-                    return dest;
-                }
-
-                if (cch_dest == 0) {
-                    /* Nope.  We only calculated the required size of the buffer */
-
-                    cch_dest = rv + NLSERRCCH;
-                    goto cont;
-                }
-
-                *pcch_dest = rv;
-
-                /* Success! */
-                return dest;
-            }
-
-        cont:
-            if (dest != ext_dest && dest)
-                free(dest);
-            dest = malloc(cch_dest * sizeof(wchar_t));
-        }
-
-        /* Failed */
-
-        if (dest != ext_dest && dest)
-            free(dest);
-
-        *pcch_dest = 0;
-        return NULL;
-    }
-}
-
-/* \brief Normalize a UTF-16 string into a UTF-8 string.
-
-   \param[in] src : Source string.
-
-   \param[in] cch_src : Count of characters in src. If the count includes the
-       NULL terminator, then the resulting string will be NULL
-       terminated.  If it is -1, then src is assumed to be NULL
-       terminated.
-
-   \param[out] adest : Destination buffer.
-
-   \param[in] cch_adest : Number of characters in the destination buffer.
-
-   Returns the number of characters stored into cch_adest. This will
-   include the terminating NULL if cch_src included the terminating
-   NULL or was -1.  If this is 0, then the operation was unsuccessful.
- */
-long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src,
-                                   char * adest, int cch_adest)
-{
-    if (cch_src < 0) {
-        size_t cch;
-
-        if (FAILED(StringCchLengthW(src, NLSMAXCCH, &cch)))
-            return CM_ERROR_TOOBIG;
-
-        cch_src = cch+1;
-    }
-
-    {
-        wchar_t nbuf[NLSMAXCCH];
-        wchar_t * normalized;
-        int cch_norm = NLSMAXCCH;
-
-        normalized = NormalizeUtf16String(src, cch_src, nbuf, &cch_norm);
-        if (normalized) {
-            cch_adest = WideCharToMultiByte(CP_UTF8, 0, normalized, cch_norm,
-                                            adest, cch_adest, NULL, 0);
-
-            if (normalized != nbuf && normalized)
-                free(normalized);
-
-            return cch_adest;
-
-        } else {
-
-            return 0;
-
-        }
-    }
-}
-
-
-/* \brief Normalize a UTF-8 string.
-
-   \param[in] src String to normalize.
-
-   \param[in] cch_src : Count of characters in src.  If this value is
-       -1, then src is assumed to be NULL terminated.  The translated
-       string will be NULL terminated only if this is -1 or the count
-       includes the terminating NULL.
-
-   \param[out] adest : Destination string.
-
-   \param[in] cch_adest : Number of characters in the destination
-       string.
-
-   Returns the number of characters stored into adest or 0 if the call
-   was unsuccessful.
- */
-long cm_NormalizeUtf8String(const char * src, int cch_src,
-                            char * adest, int cch_adest)
-{
-    wchar_t wsrcbuf[NLSMAXCCH];
-    wchar_t *wnorm;
-    int cch;
-    int cch_norm;
-
-    /* Get some edge cases out first, so we don't have to worry about
-       cch_src being 0 etc. */
-    if (cch_src == 0) {
-        return 0;
-    } else if (*src == '\0') {
-        *adest = '\0';
-        return 1;
-    }
-
-    cch = MultiByteToWideChar(CP_UTF8, 0, src, cch_src * sizeof(char),
-                             wsrcbuf, NLSMAXCCH);
-
-    if (cch == 0) {
-#ifdef DEBUG
-        DebugBreak();
-#endif
-        return 0;
-    }
-
-    cch_norm = 0;
-    wnorm = NormalizeUtf16String(wsrcbuf, cch, NULL, &cch_norm);
-    if (wnorm == NULL) {
-#ifdef DEBUG
-        DebugBreak();
-#endif
-        return 0;
-    }
-
-    cch = WideCharToMultiByte(CP_UTF8, 0, wnorm, cch_norm,
-                              adest, cch_adest * sizeof(char),
-                              NULL, FALSE);
-
-    if (wnorm)
-        free(wnorm);
-
-    return cch;
-}
index 06523bf3a6a6f8a41b5197a97bcb013ea032d165..a157d9244a17e75df93d53c4677cd2c52367eea4 100644 (file)
@@ -25,12 +25,9 @@ extern cm_space_t *cm_GetSpace(void);
 extern void cm_FreeSpace(cm_space_t *);
 
 extern long cm_MapRPCError(long error, cm_req_t *reqp);
+
 extern long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp);
+
 extern long cm_MapVLRPCError(long error, cm_req_t *reqp);
 
-extern long cm_InitNormalization(void);
-extern long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src,
-                                          char * adest, int cch_adest);
-extern long cm_NormalizeUtf8String(const char * src, int cch_src,
-                                   char * adest, int cch_adest);
 #endif /*  __CM_UTILS_H_ENV__ */
index 8346bafb11a8f199391370dc6c286b2fd1db0a61..bd98f5eae8f8d681a00fd1cf2c47cb997a15a7f4 100644 (file)
@@ -871,26 +871,27 @@ long cm_LookupSearchProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 {
     cm_lookupSearch_t *sp;
     int match;
-    char shortName[13];
-    char *matchName;
+    char matchName[MAX_PATH];
+    int looking_for_short_name = FALSE;
 
     sp = (cm_lookupSearch_t *) rockp;
 
-    matchName = dep->name;
+    cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
     if (sp->caseFold)
-        match = cm_stricmp(matchName, sp->searchNamep);
+        match = cm_stricmp_utf8(matchName, sp->searchNamep);
     else
         match = strcmp(matchName, sp->searchNamep);
 
     if (match != 0
          && sp->hasTilde
          && !cm_Is8Dot3(dep->name)) {
-        matchName = shortName;
-        cm_Gen8Dot3Name(dep, shortName, NULL);
+
+        cm_Gen8Dot3Name(dep, matchName, NULL);
         if (sp->caseFold)
-            match = cm_stricmp(matchName, sp->searchNamep);
+            match = cm_stricmp_utf8(matchName, sp->searchNamep);
         else
             match = strcmp(matchName, sp->searchNamep);
+        looking_for_short_name = TRUE;
     }
 
     if (match != 0)
@@ -900,7 +901,7 @@ long cm_LookupSearchProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
     if (!sp->caseFold) 
         sp->ExactFound = 1;
 
-    if (!sp->caseFold || matchName == shortName) {
+    if (!sp->caseFold || looking_for_short_name) {
         cm_SetFid(&sp->fid, sp->fid.cell, sp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
         return CM_ERROR_STOPNOW;
     }
@@ -1283,7 +1284,7 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
                     found = 1;
                     if (!cm_FreelanceMountPointExists(fullname, 0))
                         code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.", 1, &rock.fid);
-                    if ( stricmp(&namep[1], &fullname[1]) && 
+                    if ( cm_stricmp_utf8(&namep[1], &fullname[1]) && 
                                                !cm_FreelanceMountPointExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
                                                !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
                         code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
@@ -1293,7 +1294,7 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
                     found = 1;
                     if (!cm_FreelanceMountPointExists(fullname, 0))
                         code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid);
-                    if ( stricmp(namep, fullname) && 
+                    if ( cm_stricmp_utf8(namep, fullname) && 
                                                !cm_FreelanceMountPointExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
                                                !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
                         code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
@@ -1362,8 +1363,10 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
     if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
         /* lock the directory entry to prevent racing callback revokes */
         lock_ObtainRead(&dscp->rw);
-        if ( dscp->cbServerp != NULL && dscp->cbExpires > 0 )
+        if ( dscp->cbServerp != NULL && dscp->cbExpires > 0 ) {
+            /* Note: namep is a normalized name */
             cm_dnlcEnter(dscp, namep, tscp);
+        }
         lock_ReleaseRead(&dscp->rw);
     }
 
@@ -1523,7 +1526,7 @@ long cm_Lookup(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp,
     osi_Log2(afsd_logp, "cm_Lookup dscp 0x%p ref %d", dscp, dscp->refCount);
 #endif
 
-    if ( stricmp(namep,SMB_IOCTL_FILENAME_NOSLASH) == 0 ) {
+    if ( cm_stricmp_utf8N(namep,SMB_IOCTL_FILENAME_NOSLASH) == 0 ) {
         if (flags & CM_FLAG_CHECKPATH)
             return CM_ERROR_NOSUCHPATH;
         else
@@ -1580,7 +1583,26 @@ long cm_Lookup(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp,
         return CM_ERROR_NOSUCHFILE;
 }
 
-long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp)
+/*! \brief Unlink a file name
+
+  Encapsulates a call to RXAFS_RemoveFile().
+
+  \param[in] dscp cm_scache_t pointing at the directory containing the
+      name to be unlinked.
+
+  \param[in] namep Non-normalized name to be unlinked.  This is the
+      name that will be passed into the RXAFS_RemoveFile() call.
+
+  \param[in] normalizedName Normalized name to be unlinked.  This name
+      will be used to update the local directory caches.
+
+  \param[in] userp cm_user_t for the request.
+
+  \param[in] reqp Request tracker.
+ */
+long cm_Unlink(cm_scache_t *dscp, char *namep, char * normalizedName,
+               cm_user_t *userp, cm_req_t *reqp)
 {
     long code;
     cm_conn_t *connp;
@@ -1643,7 +1665,7 @@ long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp)
         dirop.lockType = CM_DIRLOCK_WRITE;
     }
     lock_ObtainWrite(&dscp->rw);
-    cm_dnlcRemove(dscp, namep);
+    cm_dnlcRemove(dscp, normalizedName);
     cm_SyncOpDone(dscp, NULL, sflags);
     if (code == 0) {
         cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
@@ -1656,10 +1678,10 @@ long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp)
     }
     lock_ReleaseWrite(&dscp->rw);
 
-    if (code == 0 && cm_CheckDirOpForSingleChange(&dirop)) {
+    if (code == 0 && cm_CheckDirOpForSingleChange(&dirop) && normalizedName) {
         cm_DirDeleteEntry(&dirop, namep);
 #ifdef USE_BPLUS
-        cm_BPlusDirDeleteEntry(&dirop, namep);
+        cm_BPlusDirDeleteEntry(&dirop, normalizedName);
 #endif
     }
     cm_EndDirOp(&dirop);
@@ -3126,8 +3148,26 @@ long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags,
     return code;
 }
 
-long cm_RemoveDir(cm_scache_t *dscp, char *namep, cm_user_t *userp,
-                   cm_req_t *reqp)
+/*! \brief Remove a directory
+
+  Encapsulates a call to RXAFS_RemoveDir().
+
+  \param[in] dscp cm_scache_t for the directory containing the
+      directory to be removed.
+
+  \param[in] namep Non-normalized name of the directory to be
+      removed. This will be the name that is passed in to
+      RXAFS_RemoveDir().
+
+  \param[in] normalizedNamep Normalized name used to update the local
+      directory caches.
+
+  \param[in] userp cm_user_t for the request.
+
+  \param[in] reqp Request tracker.
+*/
+long cm_RemoveDir(cm_scache_t *dscp, char *namep, char *normalizedNamep,
+                  cm_user_t *userp, cm_req_t *reqp)
 {
     cm_conn_t *connp;
     long code;
@@ -3187,16 +3227,16 @@ long cm_RemoveDir(cm_scache_t *dscp, char *namep, cm_user_t *userp,
     lock_ObtainWrite(&dscp->rw);
     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
     if (code == 0) {
-        cm_dnlcRemove(dscp, namep); 
+        cm_dnlcRemove(dscp, normalizedNamep); 
         cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
     }
     lock_ReleaseWrite(&dscp->rw);
 
     if (code == 0) {
-        if (cm_CheckDirOpForSingleChange(&dirop)) {
+        if (cm_CheckDirOpForSingleChange(&dirop) && normalizedNamep != NULL) {
             cm_DirDeleteEntry(&dirop, namep);
 #ifdef USE_BPLUS
-            cm_BPlusDirDeleteEntry(&dirop, namep);
+            cm_BPlusDirDeleteEntry(&dirop, normalizedNamep);
 #endif
         }
     }
@@ -3233,8 +3273,32 @@ long cm_Open(cm_scache_t *scp, int type, cm_user_t *userp)
     return 0;
 }       
 
-long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
-                char *newNamep, cm_user_t *userp, cm_req_t *reqp)
+/*! \brief Rename a file or directory
+
+  Encapsulates a RXAFS_Rename() call.
+
+  \param[in] oldDscp cm_scache_t for the directory containing the old
+      name.
+
+  \param[in] oldNamep Non-normalized old name.  This is the name that
+  will be passed into the RXAFS_Rename().
+
+  \param[in] normalizedOldNamep Normalized old name.  This is used for
+  updating local directory caches.
+
+  \param[in] newDscp cm_scache_t for the directory containing the new
+  name.
+
+  \param[in] newNamep New name. Normalized.
+
+  \param[in] userp cm_user_t for the request.
+
+  \param[in,out] reqp Request tracker.
+
+*/
+long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, char *normalizedOldNamep,
+               cm_scache_t *newDscp, char *newNamep, cm_user_t *userp,
+               cm_req_t *reqp)
 {
     cm_conn_t *connp;
     long code;
@@ -3264,7 +3328,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
         oneDir = 1;
         cm_BeginDirOp(oldDscp, userp, reqp, CM_DIRLOCK_NONE, &oldDirOp);
         lock_ObtainWrite(&oldDscp->rw);
-        cm_dnlcRemove(oldDscp, oldNamep);
+        cm_dnlcRemove(oldDscp, normalizedOldNamep);
         cm_dnlcRemove(oldDscp, newNamep);
         code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
                           CM_SCACHESYNC_STOREDATA);
@@ -3290,7 +3354,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
         if (oldDscp->fid.vnode < newDscp->fid.vnode) {
             cm_BeginDirOp(oldDscp, userp, reqp, CM_DIRLOCK_NONE, &oldDirOp);
             lock_ObtainWrite(&oldDscp->rw);
-            cm_dnlcRemove(oldDscp, oldNamep);
+            cm_dnlcRemove(oldDscp, normalizedOldNamep);
             code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
                               CM_SCACHESYNC_STOREDATA);
             lock_ReleaseWrite(&oldDscp->rw);
@@ -3328,7 +3392,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
             if (code == 0) {
                 cm_BeginDirOp(oldDscp, userp, reqp, CM_DIRLOCK_NONE, &oldDirOp);
                 lock_ObtainWrite(&oldDscp->rw);
-                cm_dnlcRemove(oldDscp, oldNamep);
+                cm_dnlcRemove(oldDscp, normalizedOldNamep);
                 code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
                                   CM_SCACHESYNC_STOREDATA);
                 lock_ReleaseWrite(&oldDscp->rw);
@@ -3399,7 +3463,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
         if (cm_CheckDirOpForSingleChange(&oldDirOp)) {
 
 #ifdef USE_BPLUS
-            diropCode = cm_BPlusDirLookup(&oldDirOp, oldNamep, &fileFid);
+            diropCode = cm_BPlusDirLookup(&oldDirOp, normalizedOldNamep, &fileFid);
             if (diropCode == CM_ERROR_INEXACT_MATCH)
                 diropCode = 0;
             else if (diropCode == EINVAL)
@@ -3417,7 +3481,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
                 if (diropCode == 0) { 
                     diropCode = cm_DirDeleteEntry(&oldDirOp, oldNamep);
 #ifdef USE_BPLUS
-                    cm_BPlusDirDeleteEntry(&oldDirOp, oldNamep);
+                    cm_BPlusDirDeleteEntry(&oldDirOp, normalizedOldNamep);
 #endif
                 }
             }
index 61105a505264e09daa803555216f3d47595cd27f..a72c0b114286e328b59bced79ac7c83e7b50e06f 100644 (file)
@@ -123,8 +123,8 @@ extern long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp);
 extern void cm_StatusFromAttr(struct AFSStoreStatus *statusp,
        struct cm_scache *scp, struct cm_attr *attrp);
 
-extern long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp,
-       cm_req_t *reqp);
+extern long cm_Unlink(cm_scache_t *dscp, char *namep, char * normalizedName,
+                      cm_user_t *userp, cm_req_t *reqp);
 
 extern long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
        osi_hyper_t *startOffsetp, cm_user_t *userp, cm_req_t *reqp, 
@@ -133,12 +133,13 @@ extern long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
 extern long cm_MakeDir(cm_scache_t *dscp, char *lastNamep, long flags,
        cm_attr_t *attrp, cm_user_t *userp, cm_req_t *reqp);
 
-extern long cm_RemoveDir(cm_scache_t *dscp, char *lastNamep, cm_user_t *userp,
-       cm_req_t *reqp);
+extern long cm_RemoveDir(cm_scache_t *dscp, char *lastNamep, char *originalNamep,
+                         cm_user_t *userp, cm_req_t *reqp);
 
-extern long cm_Rename(cm_scache_t *oldDscp, char *oldLastNamep,
-       cm_scache_t *newDscp, char *newLastNamep, cm_user_t *userp,
-       cm_req_t *reqp);
+extern long cm_Rename(cm_scache_t *oldDscp,
+                      char *oldLastNamep, char *normalizedOldNamep,
+                      cm_scache_t *newDscp, char *newLastNamep,
+                      cm_user_t *userp, cm_req_t *reqp);
 
 extern long cm_HandleLink(cm_scache_t *linkScp, struct cm_user *userp,
        cm_req_t *reqp);
index 7df7a03904eab66c8ff8f7f00e8156d3cd40a3f5..b0667c15525f763fcdf39a3d94bc8aea5511f218 100644 (file)
@@ -1660,9 +1660,9 @@ cm_VolumeStateByName(cm_volume_t *volp, char *volname)
     size_t len = strlen(volname);
     cm_vol_state_t *statep;
 
-    if (stricmp(".readonly", &volname[len-9]) == 0)
+    if (cm_stricmp_utf8N(".readonly", &volname[len-9]) == 0)
         statep = &volp->vol[ROVOL];
-    else if (stricmp(".backup", &volname[len-7]) == 0)
+    else if (cm_stricmp_utf8N(".backup", &volname[len-7]) == 0)
         statep = &volp->vol[BACKVOL];
     else 
         statep = &volp->vol[RWVOL];
index aa38069e2bc5141ed1f48b6716907a0db5525aef..3022855de68ec29d1403f54add8f83075ac59bdb 100644 (file)
@@ -271,7 +271,7 @@ IsFreelanceRoot(char *apath)
 
     code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1);
     if (code == 0)
-        return !stricmp("Freelance.Local.Root",space);
+        return !cm_stricmp_utf8N("Freelance.Local.Root",space);
     return 1;   /* assume it is because it is more restrictive that way */
 }
 
index 30e69e02b66c39008308c5232e25c9f0441b8477..33de83a8b05406a88d2bfe0c7b4cb7f69fb27d31 100644 (file)
@@ -1273,8 +1273,8 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
 
     lock_ObtainWrite(&smb_rctLock);
     for(unp = usernamesp; unp; unp = unp->nextp) {
-        if (stricmp(unp->name, usern) == 0 &&
-             stricmp(unp->machine, machine) == 0) {
+        if (cm_stricmp_utf8(unp->name, usern) == 0 &&
+            cm_stricmp_utf8(unp->machine, machine) == 0) {
             unp->refCount++;
             break;
         }
@@ -1304,7 +1304,7 @@ smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
     for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
         if (!uidp->unp) 
             continue;
-        if (stricmp(uidp->unp->name, usern) == 0) {
+        if (cm_stricmp_utf8(uidp->unp->name, usern) == 0) {
             uidp->refCount++;
             osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
                     vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
@@ -1640,7 +1640,7 @@ static char *smb_stristr(char *str1, char *str2)
     char *cursor;
 
     for (cursor = str1; *cursor; cursor++)
-        if (stricmp(cursor, str2) == 0)
+        if (cm_stricmp_utf8(cursor, str2) == 0)
             return cursor;
 
     return NULL;
@@ -1746,13 +1746,17 @@ long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 {
     int matchType = 0;
     smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
-    if (!strnicmp(dep->name, vrock->shareName, 12)) {
-        if(!stricmp(dep->name, vrock->shareName))
+    char normName[MAX_PATH];
+
+    cm_NormalizeUtf8String(dep->name, -1, normName, sizeof(normName)/sizeof(char));
+
+    if (!strnicmp(normName, vrock->shareName, 12)) {
+        if(!cm_stricmp_utf8(normName, vrock->shareName))
             matchType = SMB_FINDSHARE_EXACT_MATCH;
         else
             matchType = SMB_FINDSHARE_PARTIAL_MATCH;
         if(vrock->match) free(vrock->match);
-        vrock->match = strdup(dep->name);
+        vrock->match = strdup(normName);
         vrock->matchType = matchType;
 
         if(matchType == SMB_FINDSHARE_EXACT_MATCH)
@@ -1796,7 +1800,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
         RegCloseKey (parmKey);
     }
 
-    if (allSubmount && _stricmp(shareName, "all") == 0) {
+    if (allSubmount && cm_stricmp_utf8N(shareName, "all") == 0) {
         *pathNamep = NULL;
         return 1;
     }
@@ -1804,16 +1808,16 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
     /* In case, the all share is disabled we need to still be able
      * to handle ioctl requests 
      */
-    if (_stricmp(shareName, "ioctl$") == 0) {
+    if (cm_stricmp_utf8N(shareName, "ioctl$") == 0) {
         *pathNamep = strdup("/.__ioctl__");
         return 1;
     }
 
-    if (_stricmp(shareName, "IPC$") == 0 ||
-        _stricmp(shareName, "srvsvc") == 0 ||
-        _stricmp(shareName, "wkssvc") == 0 ||
-        _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
-        _stricmp(shareName, "DESKTOP.INI") == 0
+    if (cm_stricmp_utf8N(shareName, "IPC$") == 0 ||
+        cm_stricmp_utf8N(shareName, "srvsvc") == 0 ||
+        cm_stricmp_utf8N(shareName, "wkssvc") == 0 ||
+        cm_stricmp_utf8N(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
+        cm_stricmp_utf8N(shareName, "DESKTOP.INI") == 0
          ) {
         *pathNamep = NULL;
         return 0;
@@ -2002,17 +2006,17 @@ int smb_FindShareCSCPolicy(char *shareName)
     len = sizeof(policy);
     if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
          len == 0) {
-        retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
+        retval = cm_stricmp_utf8N("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
     }
-    else if (stricmp(policy, "documents") == 0)
+    else if (cm_stricmp_utf8N(policy, "documents") == 0)
     {
         retval = CSC_POLICY_DOCUMENTS;
     }
-    else if (stricmp(policy, "programs") == 0)
+    else if (cm_stricmp_utf8N(policy, "programs") == 0)
     {
         retval = CSC_POLICY_PROGRAMS;
     }
-    else if (stricmp(policy, "disable") == 0)
+    else if (cm_stricmp_utf8N(policy, "disable") == 0)
     {
         retval = CSC_POLICY_DISABLE;
     }
@@ -5259,7 +5263,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastComp, pathp);
 #ifndef SPECIAL_FOLDERS
-    if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
+    if (lastComp && cm_stricmp_utf8N(lastComp, "\\desktop.ini") == 0) {
         code = cm_NameI(rootScp, spacep->data,
                         caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
                         userp, tidPathp, &req, &dscp);
@@ -5547,8 +5551,7 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     smb_unlinkRock_t *rockp;
     int caseFold;
     int match;
-    char shortName[13];
-    char *matchName;
+    char matchName[MAX_PATH];
         
     rockp = vrockp;
 
@@ -5556,13 +5559,12 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
         caseFold |= CM_FLAG_8DOT3;
 
-    matchName = dep->name;
+    cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
     match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
     if (!match &&
          (rockp->flags & SMB_MASKFLAG_TILDE) &&
          !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        matchName = shortName;
+        cm_Gen8Dot3Name(dep, matchName, NULL);
         /* 8.3 matches are always case insensitive */
         match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
     }
@@ -5684,15 +5686,22 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_dirEntryList_t * entry;
 
         for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+            char normalizedName[MAX_PATH];
+
+            /* Note: entry->name is a non-normalized name */
 
             osi_Log1(smb_logp, "Unlinking %s",
                      osi_LogSaveString(smb_logp, entry->name));
-            code = cm_Unlink(dscp, entry->name, userp, &req);
+
+            cm_NormalizeUtf8String(entry->name, -1, normalizedName,
+                                   sizeof(normalizedName)/sizeof(char));
+
+            code = cm_Unlink(dscp, entry->name, normalizedName, userp, &req);
 
             if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_REMOVED,
                                  FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
-                                 dscp, entry->name, NULL, TRUE);
+                                 dscp, normalizedName, NULL, TRUE);
         }
     }
 
@@ -5716,7 +5725,8 @@ typedef struct smb_renameRock {
     char *maskp;               /* pointer to star pattern of old file name */
     int flags;             /* tilde, casefold, etc */
     char *newNamep;            /* ptr to the new file's name */
-    char oldName[MAX_PATH];
+    char oldName[MAX_PATH];     /* non-normalized name */
+    char normalizedOldName[MAX_PATH]; /* normalized name */
     int any;
 } smb_renameRock_t;
 
@@ -5726,26 +5736,28 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     smb_renameRock_t *rockp;
     int caseFold;
     int match;
-    char shortName[13]="";
+    char matchName[MAX_PATH];
 
     rockp = (smb_renameRock_t *) vrockp;
 
+    cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
     caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
     if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
         caseFold |= CM_FLAG_8DOT3;
 
-    match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
+    match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
     if (!match &&
         (rockp->flags & SMB_MASKFLAG_TILDE) &&
          !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
+        cm_Gen8Dot3Name(dep, matchName, NULL);
+        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
     }
 
     if (match) {
        rockp->any = 1;
-        strncpy(rockp->oldName, dep->name, sizeof(rockp->oldName)/sizeof(char) - 1);
-        rockp->oldName[sizeof(rockp->oldName)/sizeof(char) - 1] = '\0';
+        StringCbCopyA(rockp->oldName, sizeof(rockp->oldName), dep->name);
+        StringCbCopyA(rockp->normalizedOldName, sizeof(rockp->normalizedOldName),
+                      matchName);
             code = CM_ERROR_STOPNOW;
     } else {
        code = 0;
@@ -5857,6 +5869,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
     rock.newNamep = newLastNamep;
     rock.oldName[0] = '\0';
+    rock.normalizedOldName[0] = '\0';
     rock.any = 0;
 
     /* Check if the file already exists; if so return error */
@@ -5870,7 +5883,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         /* Check if the old and the new names differ only in case. If so return
          * success, else return CM_ERROR_EXISTS 
          */
-        if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+        if (!code && oldDscp == newDscp && !cm_stricmp_utf8(oldLastNamep, newLastNamep)) {
 
             /* This would be a success only if the old file is *as same as* the new file */
             code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
@@ -5912,7 +5925,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
 
     if (code == CM_ERROR_STOPNOW && rock.oldName[0] != '\0') {
-       code = cm_Rename(rock.odscp, rock.oldName,
+       code = cm_Rename(rock.odscp, rock.oldName, rock.normalizedOldName,
                          rock.ndscp, rock.newNamep, rock.userp,
                          rock.reqp);   
         /* if the call worked, stop doing the search now, since we
@@ -5933,12 +5946,12 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     if (oldDscp == newDscp) {
         if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
             smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                             filter, oldDscp, oldLastNamep,
+                             filter, oldDscp, rock.normalizedOldName,
                              newLastNamep, TRUE);
     } else {
         if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
             smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                             filter, oldDscp, oldLastNamep,
+                             filter, oldDscp, rock.normalizedOldName,
                              NULL, TRUE);
         if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH)
             smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME,
@@ -6151,22 +6164,20 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
     long code = 0;
     smb_rmdirRock_t *rockp;
     int match;
-    char shortName[13];
-    char *matchName;
+    char matchName[MAX_PATH];
         
     rockp = (smb_rmdirRock_t *) vrockp;
 
-    matchName = dep->name;
+    cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
     if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
-        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+        match = (cm_stricmp_utf8(matchName, rockp->maskp) == 0);
     else
         match = (strcmp(matchName, rockp->maskp) == 0);
     if (!match &&
          (rockp->flags & SMB_MASKFLAG_TILDE) &&
          !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        matchName = shortName;
-        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+        cm_Gen8Dot3Name(dep, matchName, NULL);
+        match = (cm_stricmp_utf8(matchName, rockp->maskp) == 0);
     }       
 
     if (match) {
@@ -6260,15 +6271,20 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_dirEntryList_t * entry;
 
         for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+            char normalizedName[MAX_PATH];
+
+            cm_NormalizeUtf8String(entry->name, -1, normalizedName,
+                                   sizeof(normalizedName)/sizeof(char));
+
             osi_Log1(smb_logp, "Removing directory %s",
                      osi_LogSaveString(smb_logp, entry->name));
 
-            code = cm_RemoveDir(dscp, entry->name, userp, &req);
+            code = cm_RemoveDir(dscp, entry->name, normalizedName, userp, &req);
 
             if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_REMOVED,
                                  FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
-                                 dscp, entry->name, NULL, TRUE);
+                                 dscp, normalizedName, NULL, TRUE);
         }
     }
 
@@ -6342,47 +6358,59 @@ struct smb_FullNameRock {
     char *name;
     cm_scache_t *vnode;
     char *fullName;
+    char *originalName;
 };
 
 int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
                      osi_hyper_t *offp)
 {
-    char shortName[13];
+    char matchName[MAX_PATH];
     struct smb_FullNameRock *vrockp;
 
     vrockp = (struct smb_FullNameRock *)rockp;
 
+    cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
+
     if (!cm_Is8Dot3(dep->name)) {
+        char shortName[13];
+
         cm_Gen8Dot3Name(dep, shortName, NULL);
 
-        if (cm_stricmp(shortName, vrockp->name) == 0) {
-            vrockp->fullName = strdup(dep->name);
+        if (cm_stricmp_utf8N(shortName, vrockp->name) == 0) {
+            vrockp->fullName = strdup(matchName);
+            vrockp->originalName = strdup(dep->name);
             return CM_ERROR_STOPNOW;
         }
     }
-    if (cm_stricmp(dep->name, vrockp->name) == 0 &&
+    if (cm_stricmp_utf8(matchName, vrockp->name) == 0 &&
         ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode &&
         ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
-        vrockp->fullName = strdup(dep->name);
+        vrockp->fullName = strdup(matchName);
+        vrockp->originalName = strdup(dep->name);
         return CM_ERROR_STOPNOW;
     }
     return 0;
 }
 
 void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
-                  char **newPathp, cm_user_t *userp, cm_req_t *reqp)
+                  char **newPathp, char ** originalPathp,
+                  cm_user_t *userp, cm_req_t *reqp)
 {
     struct smb_FullNameRock rock;
     long code = 0;
 
+    memset(&rock, 0, sizeof(rock));
     rock.name = pathp;
     rock.vnode = scp;
 
     code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL); 
-    if (code == CM_ERROR_STOPNOW)
+    if (code == CM_ERROR_STOPNOW) {
         *newPathp = rock.fullName;
-    else
+        *originalPathp = rock.originalName;
+    } else {
         *newPathp = strdup(pathp);
+        *originalPathp = strdup(pathp);
+    }
 }
 
 long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
@@ -6498,7 +6526,8 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
     }
 
     if (fidp->flags & SMB_FID_DELONCLOSE) {
-        char *fullPathp;
+        char *fullPathp = NULL;
+        char *originalNamep = NULL;
 
        lock_ReleaseMutex(&fidp->mx);
 
@@ -6507,9 +6536,9 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
             cm_HoldSCache(scp);
             delscp = scp;
         }
-        smb_FullName(dscp, delscp, pathp, &fullPathp, userp, &req);
+        smb_FullName(dscp, delscp, pathp, &fullPathp, &originalNamep, userp, &req);
         if (delscp->fileType == CM_SCACHETYPE_DIRECTORY) {
-            code = cm_RemoveDir(dscp, fullPathp, userp, &req);
+            code = cm_RemoveDir(dscp, originalNamep, fullPathp, userp, &req);
            if (code == 0) {
                if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                    smb_NotifyChange(FILE_ACTION_REMOVED,
@@ -6517,7 +6546,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
                                      dscp, fullPathp, NULL, TRUE);
            }
         } else {
-            code = cm_Unlink(dscp, fullPathp, userp, &req);
+            code = cm_Unlink(dscp, originalNamep, fullPathp, userp, &req);
            if (code == 0) {                            
                if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                    smb_NotifyChange(FILE_ACTION_REMOVED,
@@ -6525,7 +6554,12 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
                                      dscp, fullPathp, NULL, TRUE);
            }
         }
+
+        if (fullPathp)
         free(fullPathp);
+        if (originalNamep)
+            free(originalNamep);
+
        lock_ObtainMutex(&fidp->mx);
        fidp->flags &= ~SMB_FID_DELONCLOSE;
     }
index 02272312e35a1374d81bb6b53b6fa1b578187b1f..f06b03b82e117371d3ca5456338913f0c957c8bd 100644 (file)
@@ -31,6 +31,7 @@
 #include <WINNT\afsreg.h>
 
 #include "smb.h"
+#include <strsafe.h>
 
 extern osi_hyper_t hzero;
 
@@ -79,7 +80,7 @@ afs_uint32 smb_IsExecutableFileName(const char *name)
 
     for ( i=0; smb_ExecutableExtensions[i]; i++) {
         j = len - (int)strlen(smb_ExecutableExtensions[i]);
-        if (_stricmp(smb_ExecutableExtensions[i], &name[j]) == 0)
+        if (cm_stricmp_utf8N(smb_ExecutableExtensions[i], &name[j]) == 0)
             return 1;
     }
 
@@ -1536,9 +1537,9 @@ typedef struct smb_rap_share_list {
 
 int smb_rapCollectSharesProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp) {
     smb_rap_share_list_t * sp;
-    char * name;
+    char name[MAX_PATH];
 
-    name = dep->name;
+    cm_NormalizeUtf8String(dep->name, -1, name, sizeof(name)/sizeof(char));
 
     if (name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
         return 0; /* skip over '.' and '..' */
@@ -1694,7 +1695,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
             len = sizeof(thisShare);
             rv = RegEnumValue(hkSubmount, dw, thisShare, &len, NULL, NULL, NULL, NULL);
             if (rv == ERROR_SUCCESS &&
-                strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
+                strlen(thisShare) && (!allSubmount || cm_stricmp_utf8N(thisShare,"all"))) {
                 strncpy(shares[cshare].shi1_netname, thisShare,
                         sizeof(shares->shi1_netname)-1);
                 shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
@@ -1714,7 +1715,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
     for (i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
         /* in case there are collisions with submounts, submounts have higher priority */              
         for (j=0; j < nonrootShares; j++)
-            if (!stricmp(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
+            if (!cm_stricmp_utf8(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
                 break;
                
         if (j < nonrootShares) {
@@ -1800,7 +1801,7 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack
     else
         return CM_ERROR_INVAL;
 
-    if(!stricmp(shareName,"all") || !strcmp(shareName,"*.")) {
+    if(!cm_stricmp_utf8N(shareName,"all") || !strcmp(shareName,"*.")) {
         rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
                           KEY_QUERY_VALUE, &hkParam);
         if (rv == ERROR_SUCCESS) {
@@ -2271,10 +2272,10 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
     if (lastNamep && 
-         (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
-           stricmp(lastNamep, "\\srvsvc") == 0 ||
-           stricmp(lastNamep, "\\wkssvc") == 0 ||
-           stricmp(lastNamep, "\\ipc$") == 0)) {
+         (cm_stricmp_utf8N(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+           cm_stricmp_utf8N(lastNamep, "\\srvsvc") == 0 ||
+           cm_stricmp_utf8N(lastNamep, "\\wkssvc") == 0 ||
+           cm_stricmp_utf8N(lastNamep, "\\ipc$") == 0)) {
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
@@ -2749,19 +2750,25 @@ int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
                          osi_hyper_t *offp)
 {       
     struct smb_ShortNameRock *rockp;
+    char normName[MAX_PATH];
     char *shortNameEnd;
 
     rockp = vrockp;
+
+    cm_NormalizeUtf8String(dep->name, -1, normName, sizeof(normName)/sizeof(char));
+
     /* compare both names and vnodes, though probably just comparing vnodes
      * would be safe enough.
      */
-    if (cm_stricmp(dep->name, rockp->maskp) != 0)
+    if (cm_stricmp_utf8(normName, rockp->maskp) != 0)
         return 0;
     if (ntohl(dep->fid.vnode) != rockp->vnode)
         return 0;
+
     /* This is the entry */
     cm_Gen8Dot3Name(dep, rockp->shortName, &shortNameEnd);
     rockp->shortNameLen = shortNameEnd - rockp->shortName;
+
     return CM_ERROR_STOPNOW;
 }       
 
@@ -2925,7 +2932,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 #ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
-            if (stricmp(lastComp, "\\desktop.ini") == 0) {
+            if (cm_stricmp_utf8N(lastComp, "\\desktop.ini") == 0) {
                 code = cm_NameI(cm_data.rootSCachep, spacep->data,
                                  CM_FLAG_CASEFOLD
                                  | CM_FLAG_DIRSEARCH
@@ -3201,7 +3208,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 #ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
-            if (stricmp(lastComp, "\\desktop.ini") == 0) {
+            if (cm_stricmp_utf8N(lastComp, "\\desktop.ini") == 0) {
                 code = cm_NameI(cm_data.rootSCachep, spacep->data,
                                  CM_FLAG_CASEFOLD
                                  | CM_FLAG_DIRSEARCH
@@ -4212,51 +4219,86 @@ VOID initUpperCaseTable(VOID)
     mapCaseTable[(int)'>'] = toupper('?');    
 }
 
-// Compare 'pattern' (containing metacharacters '*' and '?') with the file
-// name 'name'.
-// Note : this procedure works recursively calling itself.
-// Parameters
-// PSZ pattern    : string containing metacharacters.
-// PSZ name       : file name to be compared with 'pattern'.
-// Return value
-// BOOL : TRUE/FALSE (match/mistmatch)
+/*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
+
+  \note This procedure works recursively calling itself.
 
+  \param[in] pattern string containing metacharacters.
+  \param[in] name File name to be compared with 'pattern'.
+
+  \return BOOL : TRUE/FALSE (match/mistmatch)
+*/
 BOOL 
-szWildCardMatchFileName(PSZ pattern, PSZ name, int casefold) 
+szWildCardMatchFileName(char * pattern, char * name, int casefold) 
 {
-    PSZ pename;         // points to the last 'name' character
-    PSZ p;
-    pename = name + strlen(name) - 1;
+    char upattern[MAX_PATH];
+    char uname[MAX_PATH];
+
+    char * pename;         // points to the last 'name' character
+    char * p;
+    char * pattern_next;
+
+    if (casefold) {
+        StringCbCopyA(upattern, sizeof(upattern), pattern);
+        strupr_utf8(upattern, sizeof(upattern));
+        pattern = upattern;
+
+        StringCbCopyA(uname, sizeof(uname), name);
+        strupr_utf8(uname, sizeof(uname));
+        name = uname;
+
+        /* The following translations all work on single byte
+           characters */
+        for (p=pattern; *p; p++) {
+            if (*p == '"') *p = '.'; continue;
+            if (*p == '<') *p = '*'; continue;
+            if (*p == '>') *p = '?'; continue;
+        }
+
+        for (p=name; *p; p++) {
+            if (*p == '"') *p = '.'; continue;
+            if (*p == '<') *p = '*'; continue;
+            if (*p == '>') *p = '?'; continue;
+        }
+    }
+
+    pename = char_prev_utf8(name + strlen(name));
+
     while (*name) {
         switch (*pattern) {
         case '?':
-           ++pattern;
+           pattern = char_next_utf8(pattern);
             if (*name == '.')
                continue;
-            ++name;
+            name = char_next_utf8(name);
             break;
+
          case '*':
-            ++pattern;
+            pattern = char_next_utf8(pattern);
             if (*pattern == '\0')
                 return TRUE;
-            for (p = pename; p >= name; --p) {
-                if ((casefold && (mapCaseTable[*p] == mapCaseTable[*pattern]) ||
-                     !casefold && (*p == *pattern)) &&
-                     szWildCardMatchFileName(pattern + 1, p + 1, casefold))
+
+            pattern_next = char_next_utf8(pattern);
+
+            for (p = pename; p >= name; p = char_prev_utf8(p)) {
+                if (*p == *pattern &&
+                    szWildCardMatchFileName(pattern_next,
+                                            char_next_utf8(p), FALSE))
                     return TRUE;
             } /* endfor */
             return FALSE;
+
         default:
-            if ((casefold && mapCaseTable[*name] != mapCaseTable[*pattern]) ||
-                (!casefold && *name != *pattern))
+            if (*name != *pattern)
                 return FALSE;
-            ++pattern, ++name;
+            pattern = char_next_utf8(pattern);
+            name = char_next_utf8(name);
             break;
         } /* endswitch */
     } /* endwhile */ 
 
     /* if all we have left are wildcards, then we match */
-    for (;*pattern; pattern++) {
+    for (;*pattern; pattern = char_next_utf8(pattern)) {
        if (*pattern != '*' && *pattern != '?')
            return FALSE;
     }
@@ -5108,6 +5150,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     returnedNames = 0;
     bytesInBuffer = 0;
     while (1) {
+        char normName[MAX_PATH]; /* Normalized name */
+
         op = origOp;
         if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS)
             /* skip over resume key */
@@ -5280,6 +5324,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         if (dep->fid.vnode == 0) 
             goto nextEntry;             /* This entry is not in use */
 
+        cm_NormalizeUtf8String(dep->name, -1, normName, sizeof(normName)/sizeof(char));
+
         /* Need 8.3 name? */
         NeedShortName = 0;
         if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO && 
@@ -5290,18 +5336,18 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         osi_Log4(smb_logp, "T2 search dir vn %u uniq %u name %s (%s)",
                   dep->fid.vnode, dep->fid.unique, 
-                  osi_LogSaveString(smb_logp, dep->name),
+                  osi_LogSaveString(smb_logp, normName),
                   NeedShortName ? osi_LogSaveString(smb_logp, shortName) : "");
 
         /* When matching, we are using doing a case fold if we have a wildcard mask.
          * If we get a non-wildcard match, it's a lookup for a specific file. 
          */
-        if (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
+        if (smb_V3MatchMask(normName, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
              (NeedShortName && smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD))) 
         {
             /* Eliminate entries that don't match requested attributes */
             if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && 
-                 smb_IsDotFile(dep->name)) {
+                 smb_IsDotFile(normName)) {
                 osi_Log0(smb_logp, "T2 search dir skipping hidden");
                 goto nextEntry; /* no hidden files */
             }
@@ -5324,7 +5370,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
             /* finally check if this name will fit */
             onbytes = 0;
-            smb_UnparseString(opx, NULL, dep->name, &onbytes, SMB_STRF_ANSIPATH);
+            smb_UnparseString(opx, NULL, normName, &onbytes, SMB_STRF_ANSIPATH);
             orbytes = ohbytes + onbytes;
 
             /* now, we round up the record to a 4 byte alignment,
@@ -5352,7 +5398,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             memset(origOp, 0, orbytes);
 
             onbytes = 0;
-            smb_UnparseString(opx, origOp + ohbytes, dep->name, &onbytes, SMB_STRF_ANSIPATH);
+            smb_UnparseString(opx, origOp + ohbytes, normName, &onbytes, SMB_STRF_ANSIPATH);
 
             switch (infoLevel) {
             case SMB_INFO_STANDARD:
@@ -5439,7 +5485,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
                 curPatchp->dptr = attrp;
 
-                if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
+                if (smb_hideDotFiles && smb_IsDotFile(normName)) {
                     curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
                 } else {
                     curPatchp->flags = 0;
@@ -5467,7 +5513,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         }      /* if we're including this name */
         else if (!starPattern &&
                   !foundInexact &&
-                  smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
+                  smb_V3MatchMask(normName, maskp, CM_FLAG_CASEFOLD)) {
             /* We were looking for exact matches, but here's an inexact one*/
             foundInexact = 1;
         }
@@ -5646,10 +5692,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
     if (lastNamep && 
-         (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
-           stricmp(lastNamep, "\\srvsvc") == 0 ||
-           stricmp(lastNamep, "\\wkssvc") == 0 ||
-           stricmp(lastNamep, "ipc$") == 0)) {
+         (cm_stricmp_utf8N(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+           cm_stricmp_utf8N(lastNamep, "\\srvsvc") == 0 ||
+           cm_stricmp_utf8N(lastNamep, "\\wkssvc") == 0 ||
+           cm_stricmp_utf8N(lastNamep, "ipc$") == 0)) {
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
@@ -6805,10 +6851,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%s]", shareAccess, flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
 
        if (lastNamep && 
-             (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
-               stricmp(lastNamep, "\\srvsvc") == 0 ||
-               stricmp(lastNamep, "\\wkssvc") == 0 ||
-               stricmp(lastNamep, "ipc$") == 0)) {
+             (cm_stricmp_utf8N(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+               cm_stricmp_utf8N(lastNamep, "\\srvsvc") == 0 ||
+               cm_stricmp_utf8N(lastNamep, "\\wkssvc") == 0 ||
+               cm_stricmp_utf8N(lastNamep, "ipc$") == 0)) {
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
index d9de596e48acb929b3eb7759cac2e293cb0b9452..aff603c1e071e74c6b9f8b9d0c93f979d281ed9c 100644 (file)
@@ -44,6 +44,7 @@ static int rxInitDone = 0;
 
 void Die();
 
+#if 0
 foldcmp (a, b)
     register char *a;
     register char *b; {
@@ -57,6 +58,7 @@ foldcmp (a, b)
         if (t == 0) return 0;
     }
 }
+#endif
 
 /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
 static int InAFS(register char *apath)
index 8090fdfcdb676028f52ae04bb78188ca25516169..833a509f8c7e125c17d42e431901c776660d03cf 100644 (file)
@@ -81,7 +81,8 @@ EXELIBS =\
        $(EXELIBDIR)\afs\afsutil.lib \
        $(EXELIBDIR)\afs\afseventlog.lib \
        $(EXELIBDIR)\afs\afsreg.lib \
-       $(EXELIBDIR)\cm_dns.obj
+       $(EXELIBDIR)\cm_dns.obj \
+        $(EXELIBDIR)\cm_nls.obj
 
 
 $(SETKEY_EXEFILE): $(SETKEY_EXEOBJS) $(EXELIBS)
index 9ac0c89e3c3ec394c037e19b97e7422e7fb327a0..0ed4e43ae8a5695bb354a8c48e441a8c1dc713fd 100644 (file)
@@ -67,7 +67,8 @@ BOSSERVER_EXELIBS =\
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 $(BOSSERVER_EXEFILE): $(BOSSERVER_EXEOBJS) $(BOSSERVER_EXELIBS)
        $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib
@@ -103,7 +104,8 @@ BOS_EXELIBS =\
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
        $(DESTDIR)\lib\afs\afspioctl.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 
 $(RS_BOS_EXEFILE): $(BOS_EXEOBJS) $(BOS_EXELIBS)
index 944db3dfb8cc008ab1cafd01b19c3815ade8bae0..76708fbb05212354b0d6e26bc07a78c61e17f3f5 100644 (file)
@@ -88,7 +88,8 @@ EXELIBS =\
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
        $(DESTDIR)\lib\afs\afspioctl.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
-     $(DESTDIR)\lib\cm_dns.obj
+        $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
        
 
 $(EXEFILE): $(EXEOBJS) $(EXERES) $(EXELIBS)
index 68d42599d5ea2852b41c368614ee318c2969fb25..d7d9f4a999663080b9d99ef84d8934d0404064ea 100644 (file)
@@ -77,7 +77,8 @@ EXELIBS =\
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 
 $(EXEFILE): $(EXEOBJS)  $(EXELIBS)
index 31e2dfe1a389b9daacf48ddfa3802cc155f30f91..478ed86a245bb1c7b12cb2521298de59722020b3 100644 (file)
@@ -1,3 +1,4 @@
+
 # Copyright 2000, International Business Machines Corporation and others.
 # All Rights Reserved.
 # 
@@ -52,7 +53,8 @@ EXELIBS =\
        $(DESTDIR)\lib\afs\afspioctl.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 $(EXERES): butc.rc AFS_component_version_number.h
 
index f826b3ca332e3b91d1f8d1f6aeb9ad5e7bbea726..e91596107f2c9b4acb201774758257503e331166 100644 (file)
@@ -98,7 +98,8 @@ AFSLIBS =  \
        $(DESTDIR)\lib\afsubik.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afsrxkad.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
        
 TOKENLIB = $(DESTDIR)\lib\afs\afspioctl.lib
 
index b216940d48be0d84b6f6e7b008a7e02e08d210d4..f92b1a821c7f722ac620ecdb5224306e1f0361bf 100644 (file)
@@ -96,6 +96,7 @@ DLLOBJS =\
        $(WINNTAFSDOBJS) \
        $(AUDITBJS) \
        $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj \
        $(OUT)\afsauthent.res
 
 $(RXOBJS): $(RX)\$$(@B).c
index f94543d7c1d43deefdcf792f9c7f0c330540bfbc..a3f54717fd24bde8d3282885c0d57f05dae5baa9 100644 (file)
@@ -69,7 +69,8 @@ PTSERVER_EXELIBS =\
        $(DESTDIR)\lib\afs\afsaudit.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 !IF (("$(SYS_NAME)"!="i386_win95" ) && ("$(SYS_NAME)"!="I386_WIN95" ))
 PTSERVER_EXELIBS =$(PTSERVER_EXELIBS) $(DESTDIR)\lib\afs\afsprocmgmt.lib
@@ -111,7 +112,8 @@ PTS_EXELIBS =\
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afspioctl.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 $(PTS): $(PTS_EXEOBJS) $(PTS_EXELIBS) 
        $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib
index bbac7c187be2dd8910c91a249bf6b9e7dfbe1aa2..d915bcd61ad86127748468b54369fc06f551f4de 100644 (file)
@@ -96,7 +96,8 @@ BUTCLIBS=$(DESTDIR)\lib\afs\afsbudb.lib  \
        $(DESTDIR)\lib\afspthread.lib \
 !ENDIF
             $(DESTDIR)\lib\afsdes.lib \
-            $(DESTDIR)\lib\cm_dns.obj
+            $(DESTDIR)\lib\cm_dns.obj \
+             $(DESTDIR)\lib\cm_nls.obj
 
 
 #      $(DESTDIR)\lib\afsauthent.lib \
index f11ca9d4897448cce461f94f3fb9e4b9c7fd5105..94a655d2577aac980203b4601cb43bd30ee53319 100644 (file)
@@ -22,7 +22,8 @@ LIBS = \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afsrxkad.lib \
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 ############################################################################
 # Definitions for generating files via RXGEN
index 33ed09df63e31de082855786f4e2246928ee9be1..2ca4544e04625eb66102d99ebf2ca338f0852d4c 100644 (file)
@@ -92,7 +92,8 @@ VLSERVER_EXECLIBS = \
        $(DESTDIR)\lib\afs\afseventlog.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afsprocmgmt.lib \
-       $(DESTDIR)\lib\cm_dns.obj
+       $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 $(VLSERVER): $(VLSERVER_EXEOBJS) $(LIBFILE) $(VLSERVER_EXECLIBS)
        $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib
index 632074c4fd066ec891b191f0506bc5a749005d5c..f797aafc7ef211bd8257408baa26ea3ad86b46c8 100644 (file)
@@ -70,7 +70,8 @@ EXEC_LIBS = \
        $(DESTDIR)\lib\afs\afsacl.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
-     $(DESTDIR)\lib\cm_dns.obj
+        $(DESTDIR)\lib\cm_dns.obj \
+        $(DESTDIR)\lib\cm_nls.obj
 
 
 ############################################################################