Ignore:
Timestamp:
Aug 16, 2002, 11:56:30 AM (23 years ago)
Author:
sandervl
Message:

PF: Fully implemented GetShortPathNameA/W & GetLongPathNameA/W

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/Fileio.cpp

    r8675 r9011  
    1 /* $Id: Fileio.cpp,v 1.66 2002-06-15 11:27:03 sandervl Exp $ */
     1/* $Id: Fileio.cpp,v 1.67 2002-08-16 09:56:30 sandervl Exp $ */
    22
    33/*
     
    77 * Copyright 1998 Patrick Haller
    88 *
    9  * Some parts copied from Wine (CopyFileExA/W, FindFirstFileExW)
     9 * Some parts based on Wine code (CopyFileExA/W, FindFirstFileExW,
     10 * GetShortPathNameA/W, GetLongPathNameA/W)
    1011 *
    1112 * Copyright 1993 John Burton
     
    4243#include <ctype.h>
    4344#include "fileio.h"
    44 
    45 #if 0
    46 #define IS_END_OF_NAME(ch)  (!(ch) || ((ch) == '/') || ((ch) == '\\'))
    47 #define INVALID_DOS_CHARS  "*?<>|\"+=,;[] \345"
    48 #define FILE_toupper(a)         toupper(a)
    49 #define FILE_tolower(a)         tolower(a)
     45#include <win/file.h>
     46
    5047
    5148/***********************************************************************
    5249 *           DOSFS_ValidDOSName
    5350 *
    54  * Return 1 if Unix file 'name' is also a valid MS-DOS name
     51 * Return 1 if OS/2 file 'name' is also a valid MS-DOS name
    5552 * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
    5653 * File name can be terminated by '\0', '\\' or '/'.
     
    5855static int DOSFS_ValidDOSName( const char *name, int ignore_case )
    5956{
    60     static const char invalid_chars[] = INVALID_DOS_CHARS;
     57    static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
    6158    const char *p = name;
    6259    const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
     
    9592 *           DOSFS_Hash
    9693 *
    97  * Transform a Unix file name into a hashed DOS name. If the name is a valid
     94 * Transform an OS/2 file name into a hashed DOS name. If the name is a valid
    9895 * DOS name, it is converted to upper-case; otherwise it is replaced by a
    9996 * hashed version that fits in 8.3 format.
     
    10198 * 'buffer' must be at least 13 characters long.
    10299 */
    103 void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
    104                  BOOL ignore_case )
     100
     101static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
     102                        BOOL ignore_case )
    105103{
    106104    static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
     
    185183    if (!dir_format) *dst = '\0';
    186184}
    187 #endif
     185
    188186//******************************************************************************
    189187//******************************************************************************
     
    632630 BOOL rc;
    633631
     632#if 0
     633  if((strstr(lpszFile, "odin32_") || strstr(lpszFile, "pe_")) && strstr(lpszFile, ".log")) {
     634      return TRUE;
     635  }
     636#endif
    634637  rc = OSLibDosDelete((LPSTR)lpszFile);
    635638  if(!rc) {
    636639    dprintf(("DeleteFileA %s returned FALSE; last error %x", lpszFile, GetLastError()));
    637   if(GetLastError() == 20) {
    638     return TRUE;
    639   }
     640    if(GetLastError() == ERROR_BAD_UNIT) {
     641      return TRUE;
     642    }
    640643  }
    641644  else  dprintf(("DeleteFileA %s", lpszFile));
     
    11791182                                 DWORD cchBuffer)
    11801183{
    1181  int length;
    1182 
    1183   dprintf(("KERNEL32:  GetShortPathNameA of %s, just copying it", lpszLongPath));
     1184  char  short_name[MAX_PATHNAME_LEN];  /* Long pathname in Unix format */
     1185  int length, marker = 0;
     1186  LPSTR tmpshortpath,tmplongpath;
     1187  DWORD attr, sp = 0, lp = 0;
     1188  int tmplen, drive;
     1189 
     1190  dprintf(("KERNEL32:  GetShortPathNameA %s", lpszLongPath));
    11841191
    11851192  if(!lpszLongPath) {
     
    11871194      return 0;
    11881195  }
    1189 
    1190   length = lstrlenA(lpszLongPath) + 1;
    1191   if(length > cchBuffer) {
    1192       if(lpszShortPath) {
    1193           *lpszShortPath = 0;
     1196  if (!lpszLongPath[0]) {
     1197      SetLastError(ERROR_BAD_PATHNAME);
     1198      return 0;
     1199  }
     1200
     1201  if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
     1202      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
     1203      return 0;
     1204  }
     1205
     1206  if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
     1207      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
     1208      return 0;
     1209  }
     1210 
     1211  lstrcpyA(tmplongpath,lpszLongPath);
     1212   
     1213  /* check for drive letter */
     1214  if ( lpszLongPath[1] == ':' ) {
     1215      tmpshortpath[0] = lpszLongPath[0];
     1216      tmpshortpath[1] = ':';
     1217      sp = 2;
     1218      lp = 2;
     1219    }
     1220
     1221   //todo: check drive validity!
     1222
     1223   while ( lpszLongPath[lp] ) {
     1224      marker = 0;
     1225      /* check for path delimiters and reproduce them */
     1226      if ( lpszLongPath[lp] == '\\' || lpszLongPath[lp] == '/' ) {
     1227        if (!sp || tmpshortpath[sp-1]!= '\\')
     1228        {
     1229            /* strip double "\\" */
     1230            tmpshortpath[sp] = '\\';
     1231            sp++;
     1232        }
     1233        tmpshortpath[sp]=0;/*terminate string*/
     1234        lp++;
     1235        continue;
    11941236      }
    1195       return(length); //return length required (including 0 terminator)
    1196   }
    1197   lstrcpyA(lpszShortPath, lpszLongPath);
    1198   return(length-1);
     1237
     1238      tmplen = strcspn ( lpszLongPath + lp, "\\/" );
     1239      lstrcpynA ( tmpshortpath+sp, lpszLongPath + lp, tmplen+1 );
     1240
     1241      /* Check, if the current element is a valid dos name */
     1242      if ( DOSFS_ValidDOSName ( lpszLongPath + lp, TRUE ) ) {
     1243        sp += tmplen;
     1244        lp += tmplen;
     1245        continue;
     1246      }
     1247
     1248      if (tmplongpath[lp + tmplen] == '\\')
     1249      {
     1250         tmplongpath[lp + tmplen] = 0;
     1251         marker = 1;
     1252      }
     1253
     1254      attr = GetFileAttributesA(tmplongpath);
     1255
     1256      if (attr == -1)
     1257      {
     1258         SetLastError ( ERROR_FILE_NOT_FOUND );
     1259         HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1260         HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1261         return 0;
     1262      }
     1263
     1264      DOSFS_Hash(tmpshortpath+sp, short_name, FALSE, TRUE );         
     1265       
     1266      strcpy( tmpshortpath+sp, short_name);
     1267      sp += strlen ( tmpshortpath+sp );
     1268      if (marker)
     1269         tmplongpath[lp + tmplen] = '\\';
     1270      lp += tmplen;
     1271     
     1272    }
     1273
     1274    tmpshortpath[sp] = 0;
     1275
     1276    lstrcpynA ( lpszShortPath, tmpshortpath, cchBuffer );
     1277    dprintf(("returning %s\n", lpszShortPath));
     1278    tmplen = strlen ( lpszShortPath  );
     1279
     1280    HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1281    HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1282
     1283    return tmplen;
    11991284}
    12001285//******************************************************************************
     
    12031288                                 DWORD cchBuffer)
    12041289{
    1205  int length;
    1206 
    1207   dprintf(("KERNEL32: GetShortPathNameW; just copying it"));
    1208   if(!lpszLongPath) {
    1209       SetLastError(ERROR_INVALID_PARAMETER);
    1210       return 0;
    1211   }
    1212 
    1213   length = lstrlenW(lpszLongPath) + 1;
    1214   if(length > cchBuffer) {
    1215       if(lpszShortPath) {
    1216           *lpszShortPath = 0;
    1217       }
    1218       return(length); //return length required (including 0 terminator)
    1219   }
    1220   lstrcpyW(lpszShortPath, lpszLongPath);
    1221   return(length-1);
     1290    LPSTR longpathA, shortpathA;
     1291    DWORD ret = 0;
     1292
     1293    longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszLongPath );
     1294    shortpathA = (LPSTR) HeapAlloc ( GetProcessHeap(), 0, cchBuffer );
     1295
     1296    ret = GetShortPathNameA ( longpathA, shortpathA, cchBuffer );
     1297    if (cchBuffer > 0 && !MultiByteToWideChar( CP_ACP, 0, shortpathA, -1, lpszShortPath, cchBuffer ))
     1298        lpszShortPath[cchBuffer-1] = 0;
     1299    HeapFree( GetProcessHeap(), 0, longpathA );
     1300    HeapFree( GetProcessHeap(), 0, shortpathA );
     1301
     1302    return ret;
    12221303}
    12231304//******************************************************************************
     
    12341315                               DWORD cchBuffer )
    12351316{
    1236  int length;
    1237 
    1238   dprintf(("GetLongPathNameA %x %s %d", lpszShortPath, lpszLongPath, cchBuffer));
    1239   dprintf(("WARNING: WIN98 ONLY!!"));
     1317  int tmplen;
     1318  char  short_name[MAX_PATHNAME_LEN];  /* Long pathname in Unix format */
     1319  WIN32_FIND_DATAA FindFileData;
     1320  HANDLE hFind;
     1321  DWORD sp = 0, lp = 0,attr;
     1322  LPSTR tmpshortpath,tmplongpath;
     1323
     1324   dprintf(("GetLongPathNameA %s %x %d", lpszShortPath, lpszLongPath, cchBuffer));
    12401325 
    1241   if(!lpszShortPath) {
    1242       SetLastError(ERROR_INVALID_PARAMETER);
     1326   if(!lpszShortPath) {
     1327     SetLastError(ERROR_INVALID_PARAMETER);
     1328     return 0;
     1329   }
     1330
     1331   if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
     1332      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
    12431333      return 0;
    1244   }
    1245 
    1246   length = lstrlenA(lpszShortPath) + 1;
    1247   if(length > cchBuffer) {
    1248       if(lpszLongPath) {
    1249           *lpszLongPath = 0;
     1334   }
     1335
     1336   if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
     1337      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
     1338      return 0;
     1339   }
     1340 
     1341   lstrcpyA(tmpshortpath,lpszShortPath);
     1342
     1343   /* check for drive letter */
     1344   if ( lpszShortPath[1] == ':' ) {
     1345      tmplongpath[0] = lpszShortPath[0];
     1346      tmplongpath[1] = ':';
     1347      sp = 2;
     1348      lp = 2;
     1349   }
     1350
     1351   //todo: check drive validity!
     1352
     1353   while ( lpszShortPath[lp] ) {
     1354
     1355      /* check for path delimiters and reproduce them */
     1356      if ( lpszShortPath[lp] == '\\' || lpszShortPath[lp] == '/' ) {
     1357        if (!sp || tmplongpath[sp-1]!= '\\')
     1358        {
     1359            /* strip double "\\" */
     1360            tmplongpath[sp] = '\\';
     1361            sp++;
     1362        }
     1363        tmplongpath[sp]=0;/*terminate string*/
     1364        lp++;
     1365        continue;
    12501366      }
    1251       return(length); //return length required (including 0 terminator)
    1252   }
    1253   lstrcpyA(lpszLongPath, lpszShortPath);
    1254   return(length-1);
     1367
     1368      tmplen = strcspn ( lpszShortPath + lp, "\\/" );
     1369      lstrcpynA ( tmplongpath+sp, lpszShortPath + lp, tmplen+1 );
     1370
     1371      attr = GetFileAttributesA(tmplongpath);
     1372      if (attr != -1)
     1373      {
     1374        sp += tmplen;
     1375        lp += tmplen;
     1376        continue;
     1377      }
     1378      else
     1379        // it may be hashed name or name with weird characters!
     1380        if ((tmplongpath+sp)[4] == '~')
     1381        {
     1382          //hashed entry Wine does linear dir search.. incredible.. we will be
     1383          //better ;)
     1384          if (strchr(tmplongpath+sp,'_'))
     1385          {
     1386            (tmplongpath+sp)[0] = '*';
     1387            (tmplongpath+sp)[1] = 0;
     1388          } 
     1389          else
     1390          {
     1391            (tmplongpath+sp)[4] = '*';
     1392            (tmplongpath+sp)[5] = 0;
     1393          }
     1394          hFind = FindFirstFileExA(tmplongpath, FindExInfoStandard, &FindFileData,
     1395                                   FindExSearchNameMatch, NULL, 0 );
     1396           
     1397          if (hFind == INVALID_HANDLE_VALUE)
     1398          {
     1399            //no possible variants!
     1400            SetLastError ( ERROR_FILE_NOT_FOUND );
     1401            HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1402            HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1403            return 0;
     1404          }
     1405          else
     1406           do
     1407           {
     1408             DOSFS_Hash(FindFileData.cFileName, short_name, FALSE, TRUE );         
     1409             //this happens on files like [hello world]
     1410             if (!lstrncmpA(short_name, lpszShortPath+lp, (lpszShortPath+lp+tmplen)[-1] == '.' ? tmplen-1 : tmplen ))
     1411             {
     1412               strcpy( tmplongpath+sp, FindFileData.cFileName);
     1413               sp += strlen ( tmplongpath+sp );
     1414               lp += tmplen;
     1415               break;
     1416             }
     1417            }
     1418            while (FindNextFileA(hFind, &FindFileData));
     1419           
     1420          // no FindClose() here or else GetLastError() will not give its error   
     1421          if (GetLastError() == ERROR_NO_MORE_FILES)
     1422          {
     1423             FindClose(hFind);
     1424             SetLastError ( ERROR_FILE_NOT_FOUND );
     1425             HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1426             HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1427             return 0;
     1428          }
     1429          FindClose(hFind);
     1430        }
     1431        else
     1432        {
     1433            // if this file can't be found in common or hashed files
     1434            // it does not exist
     1435            SetLastError ( ERROR_FILE_NOT_FOUND );
     1436            HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1437            HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1438            return 0;
     1439        }
     1440   }
     1441   tmplongpath[sp] = 0;
     1442
     1443   lstrcpynA ( lpszLongPath, tmplongpath, cchBuffer );
     1444   dprintf(("returning %s\n", lpszLongPath));
     1445   tmplen = strlen ( lpszLongPath  );
     1446
     1447   HeapFree ( GetProcessHeap(), 0, tmpshortpath );
     1448   HeapFree ( GetProcessHeap(), 0, tmplongpath );
     1449
     1450   return tmplen;
    12551451}
    12561452//******************************************************************************
Note: See TracChangeset for help on using the changeset viewer.