1 /* 2 * FILECOMP.C - handles filename completion. 3 * 4 * 5 * Comments: 6 * 7 * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>) 8 * moved from command.c file 9 * made second TAB display list of filename matches 10 * made filename be lower case if last character typed is lower case 11 * 12 * 25-Jan-1999 (Eric Kohl) 13 * Cleanup. Unicode safe! 14 * 15 * 30-Apr-2004 (Filip Navara <xnavara@volny.cz>) 16 * Make the file listing readable when there is a lot of long names. 17 * 18 19 * 05-Jul-2004 (Jens Collin <jens.collin@lakhei.com>) 20 * Now expands lfn even when trailing " is omitted. 21 */ 22 23 #include "precomp.h" 24 25 #ifdef FEATURE_UNIX_FILENAME_COMPLETION 26 27 VOID CompleteFilename (LPTSTR str, UINT charcount) 28 { 29 WIN32_FIND_DATA file; 30 HANDLE hFile; 31 INT curplace = 0; 32 INT start; 33 INT count; 34 INT step; 35 INT c = 0; 36 BOOL found_dot = FALSE; 37 BOOL perfectmatch = TRUE; 38 TCHAR path[MAX_PATH]; 39 TCHAR fname[MAX_PATH]; 40 TCHAR maxmatch[MAX_PATH] = _T(""); 41 TCHAR directory[MAX_PATH]; 42 LPCOMMAND cmds_ptr; 43 44 /* expand current file name */ 45 count = charcount - 1; 46 if (count < 0) 47 count = 0; 48 49 /* find how many '"'s there is typed already. */ 50 step = count; 51 while (step > 0) 52 { 53 if (str[step] == _T('"')) 54 c++; 55 step--; 56 } 57 /* if c is odd, then user typed " before name, else not. */ 58 59 /* find front of word */ 60 if (str[count] == _T('"') || (c % 2)) 61 { 62 count--; 63 while (count > 0 && str[count] != _T('"')) 64 count--; 65 } 66 else 67 { 68 while (count > 0 && str[count] != _T(' ')) 69 count--; 70 } 71 72 /* if not at beginning, go forward 1 */ 73 if (str[count] == _T(' ')) 74 count++; 75 76 start = count; 77 78 if (str[count] == _T('"')) 79 count++; /* don't increment start */ 80 81 /* extract directory from word */ 82 _tcscpy (directory, &str[count]); 83 curplace = _tcslen (directory) - 1; 84 85 if (curplace >= 0 && directory[curplace] == _T('"')) 86 directory[curplace--] = _T('\0'); 87 88 _tcscpy (path, directory); 89 90 while (curplace >= 0 && directory[curplace] != _T('\\') && 91 directory[curplace] != _T('/') && 92 directory[curplace] != _T(':')) 93 { 94 directory[curplace] = 0; 95 curplace--; 96 } 97 98 /* look for a '.' in the filename */ 99 for (count = _tcslen (directory); path[count] != _T('\0'); count++) 100 { 101 if (path[count] == _T('.')) 102 { 103 found_dot = TRUE; 104 break; 105 } 106 } 107 108 if (found_dot) 109 _tcscat (path, _T("*")); 110 else 111 _tcscat (path, _T("*.*")); 112 113 /* current fname */ 114 curplace = 0; 115 116 hFile = FindFirstFile (path, &file); 117 if (hFile != INVALID_HANDLE_VALUE) 118 { 119 /* find anything */ 120 do 121 { 122 /* ignore "." and ".." */ 123 if (!_tcscmp (file.cFileName, _T(".")) || 124 !_tcscmp (file.cFileName, _T(".."))) 125 continue; 126 127 _tcscpy (fname, file.cFileName); 128 129 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 130 _tcscat (fname, _T("\\")); 131 132 if (!maxmatch[0] && perfectmatch) 133 { 134 _tcscpy(maxmatch, fname); 135 } 136 else 137 { 138 for (count = 0; maxmatch[count] && fname[count]; count++) 139 { 140 if (tolower(maxmatch[count]) != tolower(fname[count])) 141 { 142 perfectmatch = FALSE; 143 maxmatch[count] = 0; 144 break; 145 } 146 } 147 148 if (maxmatch[count] == _T('\0') && 149 fname[count] != _T('\0')) 150 perfectmatch = FALSE; 151 } 152 } 153 while (FindNextFile (hFile, &file)); 154 155 FindClose (hFile); 156 157 /* only quote if the filename contains spaces */ 158 if (_tcschr(directory, _T(' ')) || 159 _tcschr(maxmatch, _T(' '))) 160 { 161 str[start] = _T('\"'); 162 _tcscpy (&str[start+1], directory); 163 _tcscat (&str[start], maxmatch); 164 _tcscat (&str[start], _T("\"") ); 165 } 166 else 167 { 168 _tcscpy (&str[start], directory); 169 _tcscat (&str[start], maxmatch); 170 } 171 172 if (!perfectmatch) 173 { 174 MessageBeep (-1); 175 } 176 } 177 else 178 { 179 /* no match found - search for internal command */ 180 for (cmds_ptr = cmds; cmds_ptr->name; cmds_ptr++) 181 { 182 if (!_tcsnicmp (&str[start], cmds_ptr->name, 183 _tcslen (&str[start]))) 184 { 185 /* return the mach only if it is unique */ 186 if (_tcsnicmp (&str[start], (cmds_ptr+1)->name, _tcslen (&str[start]))) 187 _tcscpy (&str[start], cmds_ptr->name); 188 break; 189 } 190 } 191 192 MessageBeep (-1); 193 } 194 } 195 196 197 /* 198 * returns 1 if at least one match, else returns 0 199 */ 200 BOOL ShowCompletionMatches (LPTSTR str, INT charcount) 201 { 202 WIN32_FIND_DATA file; 203 HANDLE hFile; 204 BOOL found_dot = FALSE; 205 INT curplace = 0; 206 INT count; 207 TCHAR path[MAX_PATH]; 208 TCHAR fname[MAX_PATH]; 209 TCHAR directory[MAX_PATH]; 210 SHORT screenwidth; 211 212 /* expand current file name */ 213 count = charcount - 1; 214 if (count < 0) 215 count = 0; 216 217 /* find front of word */ 218 if (str[count] == _T('"')) 219 { 220 count--; 221 while (count > 0 && str[count] != _T('"')) 222 count--; 223 } 224 else 225 { 226 while (count > 0 && str[count] != _T(' ')) 227 count--; 228 } 229 230 /* if not at beginning, go forward 1 */ 231 if (str[count] == _T(' ')) 232 count++; 233 234 if (str[count] == _T('"')) 235 count++; 236 237 /* extract directory from word */ 238 _tcscpy (directory, &str[count]); 239 curplace = _tcslen (directory) - 1; 240 241 if (curplace >= 0 && directory[curplace] == _T('"')) 242 directory[curplace--] = _T('\0'); 243 244 _tcscpy (path, directory); 245 246 while (curplace >= 0 && 247 directory[curplace] != _T('\\') && 248 directory[curplace] != _T(':')) 249 { 250 directory[curplace] = 0; 251 curplace--; 252 } 253 254 /* look for a . in the filename */ 255 for (count = _tcslen (directory); path[count] != _T('\0'); count++) 256 { 257 if (path[count] == _T('.')) 258 { 259 found_dot = TRUE; 260 break; 261 } 262 } 263 264 if (found_dot) 265 _tcscat (path, _T("*")); 266 else 267 _tcscat (path, _T("*.*")); 268 269 /* current fname */ 270 curplace = 0; 271 272 hFile = FindFirstFile (path, &file); 273 if (hFile != INVALID_HANDLE_VALUE) 274 { 275 UINT longestfname = 0; 276 /* Get the size of longest filename first. */ 277 do 278 { 279 if (_tcslen(file.cFileName) > longestfname) 280 { 281 longestfname = _tcslen(file.cFileName); 282 /* Directories get extra brackets around them. */ 283 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 284 longestfname += 2; 285 } 286 } 287 while (FindNextFile (hFile, &file)); 288 FindClose (hFile); 289 290 hFile = FindFirstFile (path, &file); 291 292 /* Count the highest number of columns */ 293 GetScreenSize(&screenwidth, NULL); 294 295 /* For counting columns of output */ 296 count = 0; 297 298 /* Increase by the number of spaces behind file name */ 299 longestfname += 3; 300 301 /* find anything */ 302 ConOutChar(_T('\n')); 303 do 304 { 305 /* ignore . and .. */ 306 if (!_tcscmp (file.cFileName, _T(".")) || 307 !_tcscmp (file.cFileName, _T(".."))) 308 continue; 309 310 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 311 _stprintf (fname, _T("[%s]"), file.cFileName); 312 else 313 _tcscpy (fname, file.cFileName); 314 315 ConOutPrintf (_T("%*s"), - longestfname, fname); 316 count++; 317 /* output as much columns as fits on the screen */ 318 if (count >= (screenwidth / longestfname)) 319 { 320 /* print the new line only if we aren't on the 321 * last column, in this case it wraps anyway */ 322 if (count * longestfname != (UINT)screenwidth) 323 ConOutChar(_T('\n')); 324 count = 0; 325 } 326 } 327 while (FindNextFile (hFile, &file)); 328 329 FindClose (hFile); 330 331 if (count) 332 ConOutChar(_T('\n')); 333 } 334 else 335 { 336 /* no match found */ 337 MessageBeep (-1); 338 return FALSE; 339 } 340 341 return TRUE; 342 } 343 #endif 344 345 #ifdef FEATURE_4NT_FILENAME_COMPLETION 346 347 typedef struct _FileName 348 { 349 TCHAR Name[MAX_PATH]; 350 } FileName; 351 352 VOID FindPrefixAndSuffix(LPTSTR strIN, LPTSTR szPrefix, LPTSTR szSuffix) 353 { 354 /* String that is to be examined */ 355 TCHAR str[MAX_PATH]; 356 /* temp pointers to used to find needed parts */ 357 TCHAR * szSearch; 358 TCHAR * szSearch1; 359 TCHAR * szSearch2; 360 TCHAR * szSearch3; 361 /* number of quotes in the string */ 362 INT nQuotes = 0; 363 /* used in for loops */ 364 UINT i; 365 /* Char number to break the string at */ 366 INT PBreak = 0; 367 INT SBreak = 0; 368 /* when phrasing a string, this tells weather 369 you are inside quotes ot not. */ 370 BOOL bInside = FALSE; 371 372 szPrefix[0] = _T('\0'); 373 szSuffix[0] = _T('\0'); 374 375 /* Copy over the string to later be edited */ 376 _tcscpy(str,strIN); 377 378 /* Count number of " */ 379 for(i = 0; i < _tcslen(str); i++) 380 { 381 if (str[i] == _T('\"')) 382 nQuotes++; 383 } 384 385 /* Find the prefix and suffix */ 386 if (nQuotes % 2 && nQuotes >= 1) 387 { 388 /* Odd number of quotes. Just start from the last " */ 389 /* THis is the way MS does it, and is an easy way out */ 390 szSearch = _tcsrchr(str, _T('\"')); 391 /* Move to the next char past the " */ 392 szSearch++; 393 _tcscpy(szSuffix,szSearch); 394 /* Find the one closest to end */ 395 szSearch1 = _tcsrchr(str, _T('\"')); 396 szSearch2 = _tcsrchr(str, _T('\\')); 397 szSearch3 = _tcsrchr(str, _T('/')); 398 if ((szSearch2 != NULL) && (szSearch1 < szSearch2)) 399 szSearch = szSearch2; 400 else if ((szSearch3 != NULL) && (szSearch1 < szSearch3)) 401 szSearch = szSearch3; 402 else 403 szSearch = szSearch1; 404 /* Move one char past */ 405 szSearch++; 406 szSearch[0] = _T('\0'); 407 _tcscpy(szPrefix,str); 408 return; 409 410 } 411 412 if (!_tcschr(str, _T(' '))) 413 { 414 /* No spaces, everything goes to Suffix */ 415 _tcscpy(szSuffix,str); 416 /* look for a slash just in case */ 417 szSearch = _tcsrchr(str, _T('\\')); 418 if (szSearch) 419 { 420 szSearch++; 421 szSearch[0] = _T('\0'); 422 _tcscpy(szPrefix,str); 423 } 424 else 425 { 426 szPrefix[0] = _T('\0'); 427 } 428 return; 429 } 430 431 if (!nQuotes) 432 { 433 /* No quotes, and there is a space*/ 434 /* Take it after the last space */ 435 szSearch = _tcsrchr(str, _T(' ')); 436 szSearch++; 437 _tcscpy(szSuffix,szSearch); 438 /* Find the closest to the end space or \ */ 439 _tcscpy(str,strIN); 440 szSearch1 = _tcsrchr(str, _T(' ')); 441 szSearch2 = _tcsrchr(str, _T('\\')); 442 szSearch3 = _tcsrchr(str, _T('/')); 443 if ((szSearch2 != NULL) && (szSearch1 < szSearch2)) 444 szSearch = szSearch2; 445 else if ((szSearch3 != NULL) && (szSearch1 < szSearch3)) 446 szSearch = szSearch3; 447 else 448 szSearch = szSearch1; 449 szSearch++; 450 szSearch[0] = _T('\0'); 451 _tcscpy(szPrefix,str); 452 return; 453 } 454 455 /* All else fails and there is a lot of quotes, spaces and | 456 Then we search through and find the last space or \ that is 457 not inside a quotes */ 458 for(i = 0; i < _tcslen(str); i++) 459 { 460 if (str[i] == _T('\"')) 461 bInside = !bInside; 462 if (str[i] == _T(' ') && !bInside) 463 SBreak = i; 464 if ((str[i] == _T(' ') || str[i] == _T('\\')) && !bInside) 465 PBreak = i; 466 } 467 SBreak++; 468 PBreak++; 469 _tcscpy(szSuffix,&strIN[SBreak]); 470 strIN[PBreak] = _T('\0'); 471 _tcscpy(szPrefix,strIN); 472 if (szPrefix[_tcslen(szPrefix) - 2] == _T('\"') && 473 szPrefix[_tcslen(szPrefix) - 1] != _T(' ')) 474 { 475 /* need to remove the " right before a \ at the end to 476 allow the next stuff to stay inside one set of quotes 477 otherwise you would have multiple sets of quotes*/ 478 _tcscpy(&szPrefix[_tcslen(szPrefix) - 2],_T("\\")); 479 } 480 } 481 482 int __cdecl compare(const void *arg1,const void *arg2) 483 { 484 FileName * File1; 485 FileName * File2; 486 INT ret; 487 488 File1 = cmd_alloc(sizeof(FileName)); 489 if (!File1) 490 return 0; 491 492 File2 = cmd_alloc(sizeof(FileName)); 493 if (!File2) 494 { 495 cmd_free(File1); 496 return 0; 497 } 498 499 memcpy(File1,arg1,sizeof(FileName)); 500 memcpy(File2,arg2,sizeof(FileName)); 501 502 /* ret = _tcsicmp(File1->Name, File2->Name); */ 503 ret = lstrcmpi(File1->Name, File2->Name); 504 505 cmd_free(File1); 506 cmd_free(File2); 507 return ret; 508 } 509 510 BOOL 511 FileNameContainsSpecialCharacters(LPTSTR pszFileName) 512 { 513 TCHAR chr; 514 515 while ((chr = *pszFileName++) != _T('\0')) 516 { 517 if ((chr == _T(' ')) || 518 (chr == _T('!')) || 519 (chr == _T('%')) || 520 (chr == _T('&')) || 521 (chr == _T('(')) || 522 (chr == _T(')')) || 523 (chr == _T('{')) || 524 (chr == _T('}')) || 525 (chr == _T('[')) || 526 (chr == _T(']')) || 527 (chr == _T('=')) || 528 (chr == _T('\'')) || 529 (chr == _T('`')) || 530 (chr == _T(',')) || 531 (chr == _T(';')) || 532 (chr == _T('^')) || 533 (chr == _T('~')) || 534 (chr == _T('+')) || 535 (chr == 0xB4)) // '´' 536 { 537 return TRUE; 538 } 539 } 540 541 return FALSE; 542 } 543 544 545 VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, UINT cusor) 546 { 547 /* Length of string before we complete it */ 548 INT_PTR StartLength; 549 /* Length of string after completed */ 550 //INT EndLength; 551 /* The number of chars added too it */ 552 //static INT DiffLength = 0; 553 /* Used to find and assemble the string that is returned */ 554 TCHAR szBaseWord[MAX_PATH]; 555 TCHAR szPrefix[MAX_PATH]; 556 TCHAR szOriginal[MAX_PATH]; 557 TCHAR szSearchPath[MAX_PATH]; 558 /* Save the strings used last time, so if they hit tab again */ 559 static TCHAR LastReturned[MAX_PATH]; 560 static TCHAR LastSearch[MAX_PATH]; 561 static TCHAR LastPrefix[MAX_PATH]; 562 /* Used to search for files */ 563 HANDLE hFile; 564 WIN32_FIND_DATA file; 565 /* List of all the files */ 566 FileName * FileList = NULL; 567 /* Number of files */ 568 INT FileListSize = 0; 569 /* Used for loops */ 570 UINT i; 571 /* Editable string of what was passed in */ 572 TCHAR str[MAX_PATH]; 573 /* Keeps track of what element was last selected */ 574 static INT Sel; 575 BOOL NeededQuote = FALSE; 576 BOOL ShowAll = TRUE; 577 TCHAR * line = strIN; 578 579 strOut[0] = _T('\0'); 580 581 while (_istspace (*line)) 582 line++; 583 if (!_tcsnicmp (line, _T("rd "), 3) || !_tcsnicmp (line, _T("cd "), 3)) 584 ShowAll = FALSE; 585 586 /* Copy the string, str can be edited and original should not be */ 587 _tcscpy(str,strIN); 588 _tcscpy(szOriginal,strIN); 589 590 /* Look to see if the cusor is not at the end of the string */ 591 if ((cusor + 1) < _tcslen(str)) 592 str[cusor] = _T('\0'); 593 594 /* Look to see if they hit tab again, if so cut off the diff length */ 595 if (_tcscmp(str,LastReturned) || !_tcslen(str)) 596 { 597 /* We need to know how many chars we added from the start */ 598 StartLength = _tcslen(str); 599 600 /* no string, we need all files in that directory */ 601 if (!StartLength) 602 { 603 _tcscat(str,_T("*")); 604 } 605 606 /* Zero it out first */ 607 szBaseWord[0] = _T('\0'); 608 szPrefix[0] = _T('\0'); 609 610 /*What comes out of this needs to be: 611 szBaseWord = path no quotes to the object 612 szPrefix = what leads up to the filename 613 no quote at the END of the full name */ 614 FindPrefixAndSuffix(str,szPrefix,szBaseWord); 615 /* Strip quotes */ 616 for(i = 0; i < _tcslen(szBaseWord); ) 617 { 618 if (szBaseWord[i] == _T('\"')) 619 memmove(&szBaseWord[i],&szBaseWord[i + 1], _tcslen(&szBaseWord[i]) * sizeof(TCHAR)); 620 else 621 i++; 622 } 623 624 /* clear it out */ 625 memset(szSearchPath, 0, sizeof(szSearchPath)); 626 627 /* Start the search for all the files */ 628 GetFullPathName(szBaseWord, MAX_PATH, szSearchPath, NULL); 629 630 /* Got a device path? Fallback to the the current dir plus the short path */ 631 if (szSearchPath[0] == _T('\\') && szSearchPath[1] == _T('\\') && 632 szSearchPath[2] == _T('.') && szSearchPath[3] == _T('\\')) 633 { 634 GetCurrentDirectory(MAX_PATH, szSearchPath); 635 _tcscat(szSearchPath, _T("\\")); 636 _tcscat(szSearchPath, szBaseWord); 637 } 638 639 if (StartLength > 0) 640 { 641 _tcscat(szSearchPath,_T("*")); 642 } 643 _tcscpy(LastSearch,szSearchPath); 644 _tcscpy(LastPrefix,szPrefix); 645 } 646 else 647 { 648 _tcscpy(szSearchPath, LastSearch); 649 _tcscpy(szPrefix, LastPrefix); 650 StartLength = 0; 651 } 652 /* search for the files it might be */ 653 hFile = FindFirstFile (szSearchPath, &file); 654 if (hFile == INVALID_HANDLE_VALUE) 655 { 656 /* Assemble the original string and return */ 657 _tcscpy(strOut,szOriginal); 658 return; 659 } 660 661 /* assemble a list of all files names */ 662 do 663 { 664 FileName * oldFileList = FileList; 665 666 if (!_tcscmp (file.cFileName, _T(".")) || 667 !_tcscmp (file.cFileName, _T(".."))) 668 continue; 669 670 /* Don't show files when they are doing 'cd' or 'rd' */ 671 if (!ShowAll && 672 file.dwFileAttributes != INVALID_FILE_ATTRIBUTES && 673 !(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 674 { 675 continue; 676 } 677 678 /* Add the file to the list of files */ 679 FileList = cmd_realloc(FileList, ++FileListSize * sizeof(FileName)); 680 681 if (FileList == NULL) 682 { 683 /* Don't leak old buffer */ 684 cmd_free(oldFileList); 685 /* Assemble the original string and return */ 686 _tcscpy(strOut,szOriginal); 687 FindClose(hFile); 688 ConOutFormatMessage (GetLastError()); 689 return; 690 } 691 /* Copies the file name into the struct */ 692 _tcscpy(FileList[FileListSize-1].Name,file.cFileName); 693 694 } while(FindNextFile(hFile,&file)); 695 696 FindClose(hFile); 697 698 /* Check the size of the list to see if we found any matches */ 699 if (FileListSize == 0) 700 { 701 _tcscpy(strOut,szOriginal); 702 if (FileList != NULL) 703 cmd_free(FileList); 704 return; 705 706 } 707 /* Sort the files */ 708 qsort(FileList,FileListSize,sizeof(FileName), compare); 709 710 /* Find the next/previous */ 711 if (_tcslen(szOriginal) && !_tcscmp(szOriginal,LastReturned)) 712 { 713 if (bNext) 714 { 715 if (FileListSize - 1 == Sel) 716 Sel = 0; 717 else 718 Sel++; 719 } 720 else 721 { 722 if (!Sel) 723 Sel = FileListSize - 1; 724 else 725 Sel--; 726 } 727 } 728 else 729 { 730 Sel = 0; 731 } 732 733 /* nothing found that matched last time so return the first thing in the list */ 734 strOut[0] = _T('\0'); 735 736 /* Special character in the name */ 737 if (FileNameContainsSpecialCharacters(FileList[Sel].Name)) 738 { 739 INT LastSpace; 740 BOOL bInside; 741 /* It needs a " at the end */ 742 NeededQuote = TRUE; 743 LastSpace = -1; 744 bInside = FALSE; 745 /* Find the place to put the " at the start */ 746 for(i = 0; i < _tcslen(szPrefix); i++) 747 { 748 if (szPrefix[i] == _T('\"')) 749 bInside = !bInside; 750 if (szPrefix[i] == _T(' ') && !bInside) 751 LastSpace = i; 752 } 753 754 /* insert the quotation and move things around */ 755 if (szPrefix[LastSpace + 1] != _T('\"') && LastSpace != -1) 756 { 757 memmove ( &szPrefix[LastSpace+1], &szPrefix[LastSpace], (_tcslen(szPrefix)-LastSpace+1) * sizeof(TCHAR) ); 758 759 if ((UINT)(LastSpace + 1) == _tcslen(szPrefix)) 760 { 761 _tcscat(szPrefix,_T("\"")); 762 } 763 szPrefix[LastSpace + 1] = _T('\"'); 764 } 765 else if (LastSpace == -1) 766 { 767 /* Add quotation only if none exists already */ 768 if (szPrefix[0] != _T('\"')) 769 { 770 _tcscpy(szBaseWord,_T("\"")); 771 _tcscat(szBaseWord,szPrefix); 772 _tcscpy(szPrefix,szBaseWord); 773 } 774 } 775 } 776 777 _tcscpy(strOut,szPrefix); 778 _tcscat(strOut,FileList[Sel].Name); 779 780 /* check for odd number of quotes means we need to close them */ 781 if (!NeededQuote) 782 { 783 for(i = 0; i < _tcslen(strOut); i++) 784 { 785 if (strOut[i] == _T('\"')) 786 NeededQuote = !NeededQuote; 787 } 788 } 789 790 if (NeededQuote || (_tcslen(szPrefix) && szPrefix[_tcslen(szPrefix) - 1] == _T('\"'))) 791 _tcscat(strOut,_T("\"")); 792 793 _tcscpy(LastReturned,strOut); 794 //EndLength = _tcslen(strOut); 795 //DiffLength = EndLength - StartLength; 796 if (FileList != NULL) 797 cmd_free(FileList); 798 } 799 #endif 800