#include "lfn.h" #pragma hdrstop PMYTEXTFILE ReadRenameFile( IN PCWSTR DriveRootPath ); BOOLEAN FindSections( IN PMYTEXTFILE TextFile ); BOOLEAN GetLine( IN PWCHAR StartOfLine, OUT PWSTR LineBuffer, IN ULONG BufferSizeChars, OUT PWCHAR *StartOfNextLine ); int __cdecl ComparePaths( const void *p1, const void *p2 ); PMYTEXTFILE LoadRenameFile( IN PCWSTR DriveRootPath ) { PMYTEXTFILE TextFile; BOOLEAN b; // // Read in the file. // if(TextFile = ReadRenameFile(DriveRootPath)) { if(b = FindSections(TextFile)) { return(TextFile); } UnloadRenameFile(&TextFile); } return(FALSE); } VOID UnloadRenameFile( IN OUT PMYTEXTFILE *TextFile ) { PMYTEXTFILE textFile; ULONG u; textFile = *TextFile; *TextFile = NULL; if(textFile->Sections) { for(u=0; uSectionCount; u++) { FREE(textFile->Sections[u].Name); } FREE(textFile->Sections); } FREE(textFile); } PMYTEXTFILE ReadRenameFile( IN PCWSTR DriveRootPath ) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; IO_STATUS_BLOCK IoStatusBlock; WCHAR FullPath[NTMAXPATH] = {0}; HANDLE Handle; FILE_STANDARD_INFORMATION FileInfo; PVOID Buffer; PWCHAR UnicodeBuffer; ULONG u; PMYTEXTFILE p = NULL; ULONG CharCount; wcsncpy(FullPath,DriveRootPath,sizeof(FullPath)/sizeof(FullPath[0]) - 1); ConcatenatePaths(FullPath,WINNT_OEM_LFNLIST_W,NTMAXPATH); // // Open the file. // INIT_OBJA(&ObjectAttributes,&UnicodeString,FullPath); Status = NtCreateFile( &Handle, FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE, NULL, 0 ); if(!NT_SUCCESS(Status)) { KdPrint(("LFN: Unable to open %ws (%x)\n",FullPath,Status)); goto c0; } // // Determine the size of the file. // Status = NtQueryInformationFile( Handle, &IoStatusBlock, &FileInfo, sizeof(FileInfo), FileStandardInformation ); if(!NT_SUCCESS(Status)) { KdPrint(("LFN: Unable to determine size of %ws (%x)\n",FullPath,Status)); goto c1; } // // Allocate a chunk of memory and read the file in. // Buffer = MALLOC(FileInfo.EndOfFile.LowPart); if(!Buffer) { KdPrint(("LFN: malloc failed\n")); goto c1; } Status = NtReadFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, FileInfo.EndOfFile.LowPart, NULL, NULL ); if(!NT_SUCCESS(Status)) { KdPrint(( "LFN: Unable to read %u bytes from file %ws (%x)\n", FileInfo.EndOfFile.LowPart, FullPath, Status )); goto c2; } // // Allocate a buffer for unicode conversion. // Leave room for a terminating NUL. // UnicodeBuffer = MALLOC((FileInfo.EndOfFile.LowPart+1)*sizeof(WCHAR)); if(!UnicodeBuffer) { KdPrint(("LFN: malloc failed\n")); goto c2; } // // Convert to unicode. // Status = RtlOemToUnicodeN( UnicodeBuffer, FileInfo.EndOfFile.LowPart*sizeof(WCHAR), &CharCount, Buffer, FileInfo.EndOfFile.LowPart ); if(!NT_SUCCESS(Status)) { KdPrint(("LFN: Unable to convert file data to unicode (%x)\n",Status)); goto c3; } CharCount /= sizeof(WCHAR); // // Nul-terminate the buffer and change instances of CR and control-z // to spaces. Also make sure there are no 0 chars in the buffer. // for(u=0; uText = UnicodeBuffer; UnicodeBuffer[CharCount] = 0; c3: if(!NT_SUCCESS(Status)) { FREE(UnicodeBuffer); } c2: FREE(Buffer); c1: NtClose(Handle); c0: return(NT_SUCCESS(Status) ? p : NULL); } BOOLEAN FindSections( IN PMYTEXTFILE TextFile ) { PWCHAR p,n; WCHAR Line[2*NTMAXPATH]; PWCHAR e; PVOID NewArray; PWCHAR s; PWSTR SectionName; for(p=TextFile->Text; GetLine(p,Line,sizeof(Line)/sizeof(WCHAR),&n); p=n) { // // If this is a section save it away in a table of section names. // if(Line[0] == L'[') { s = Line+1; while((*s == L' ') || (*s == L'\t')) { s++; } if(*s == L'\\') { s++; } // // Find the end, which is either the ] or a nul. // Strip off trailing spaces. // if(e = wcschr(s,L']')) { *e = 0; } else { e = wcschr(s,0); } while((*(e-1) == L' ') || (*(e-1) == L'\t')) { e--; *e = 0; } if(SectionName = MALLOC((wcslen(s)+1)*sizeof(WCHAR))) { wcscpy(SectionName,s); if(TextFile->SectionCount == TextFile->SectionArraySize) { if(TextFile->SectionCount) { NewArray = REALLOC(TextFile->Sections,(TextFile->SectionCount+10)*sizeof(MYSECTION)); } else { NewArray = MALLOC(10*sizeof(MYSECTION)); } if(NewArray) { TextFile->Sections = NewArray; TextFile->SectionArraySize += 10; } else { FREE(SectionName); KdPrint(("LFN: malloc failed\n")); return(FALSE); } } TextFile->Sections[TextFile->SectionCount].Name = SectionName; TextFile->Sections[TextFile->SectionCount].Data = n; TextFile->SectionCount++; } else { KdPrint(("LFN: malloc failed\n")); return(FALSE); } } } // // Now sort the sections by name. // qsort(TextFile->Sections,TextFile->SectionCount,sizeof(MYSECTION),ComparePaths); return(TRUE); } BOOLEAN GetLineInSection( IN PWCHAR StartOfLine, OUT PWSTR LineBuffer, IN ULONG BufferSizeChars, OUT PWCHAR *StartOfNextLine ) { // // Get the line and check if we've reached the end of the section. // if(!GetLine(StartOfLine,LineBuffer,BufferSizeChars,StartOfNextLine) || (LineBuffer[0] == L'[')) { return(FALSE); } return(TRUE); } BOOLEAN GetLine( IN PWCHAR StartOfLine, OUT PWSTR LineBuffer, IN ULONG BufferSizeChars, OUT PWCHAR *StartOfNextLine ) { PWCHAR LineEnd; SIZE_T Count; while(1) { // // Skip space chars. // while(*StartOfLine && ((*StartOfLine == L' ') || (*StartOfLine == L'\t'))) { StartOfLine++; } if(*StartOfLine == 0) { // // Nothing left. // return(FALSE); } // // Find the end of the line, which is either the newline or nul. // if(LineEnd = wcschr(StartOfLine,L'\n')) { *StartOfNextLine = LineEnd+1; } else { LineEnd = wcschr(StartOfLine,0); *StartOfNextLine = LineEnd; } // // Ignore this line if it's a comment or empty. // Otherwise return it. // if((*StartOfLine != L';') && (*StartOfLine != L' ')) { Count = LineEnd - StartOfLine; if(Count >= BufferSizeChars) { Count = BufferSizeChars-1; } RtlCopyMemory(LineBuffer,StartOfLine,Count*sizeof(WCHAR)); LineBuffer[Count] = 0; return(TRUE); } StartOfLine = *StartOfNextLine; } } int __cdecl ComparePaths( const void *p1, const void *p2 ) { unsigned u1,u2; PWCHAR s1,s2; // // Count \'s in each. The one with fewer is 'greater'. // s1 = ((PMYSECTION)p1)->Name; s2 = ((PMYSECTION)p2)->Name; u1 = 0; u2 = 0; while(*s1) { if(*s1 == L'\\') { u1++; } s1++; } while(*s2) { if(*s2 == L'\\') { u2++; } s2++; } if(u1 == u2) { return(0); } return((u1 < u2) ? 1 : -1); } BOOLEAN ParseLine( IN OUT PWSTR Line, OUT PWSTR *LHS, OUT PWSTR *RHS ) { PWCHAR p,q; // // We rely on the routines abive to have stripped out // leading spaces. // *LHS = Line; // // Find the equals. The LHS isn't allowed to be quoted. // Strip trailing space off the LHS. // p = wcschr(Line,L'='); if(!p || (p == Line)) { return(FALSE); } q = p+1; *p-- = 0; while((*p == L' ') || (*p == L'\t')) { *p-- = 0; } while(*q && ((*q == L' ') || (*q == L'\t'))) { q++; } if(*q == 0) { return(FALSE); } if(*q == L'\"') { q++; } *RHS = q; p = q + wcslen(q); p--; while((*p == L' ') || (*p == L'\t')) { *p-- = 0; } if(*p == L'\"') { *p = 0; } return(TRUE); }