Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
10 KiB

  1. #include "lfn.h"
  2. #pragma hdrstop
  3. PMYTEXTFILE
  4. ReadRenameFile(
  5. IN PCWSTR DriveRootPath
  6. );
  7. BOOLEAN
  8. FindSections(
  9. IN PMYTEXTFILE TextFile
  10. );
  11. BOOLEAN
  12. GetLine(
  13. IN PWCHAR StartOfLine,
  14. OUT PWSTR LineBuffer,
  15. IN ULONG BufferSizeChars,
  16. OUT PWCHAR *StartOfNextLine
  17. );
  18. int
  19. __cdecl
  20. ComparePaths(
  21. const void *p1,
  22. const void *p2
  23. );
  24. PMYTEXTFILE
  25. LoadRenameFile(
  26. IN PCWSTR DriveRootPath
  27. )
  28. {
  29. PMYTEXTFILE TextFile;
  30. BOOLEAN b;
  31. //
  32. // Read in the file.
  33. //
  34. if(TextFile = ReadRenameFile(DriveRootPath)) {
  35. if(b = FindSections(TextFile)) {
  36. return(TextFile);
  37. }
  38. UnloadRenameFile(&TextFile);
  39. }
  40. return(FALSE);
  41. }
  42. VOID
  43. UnloadRenameFile(
  44. IN OUT PMYTEXTFILE *TextFile
  45. )
  46. {
  47. PMYTEXTFILE textFile;
  48. ULONG u;
  49. textFile = *TextFile;
  50. *TextFile = NULL;
  51. if(textFile->Sections) {
  52. for(u=0; u<textFile->SectionCount; u++) {
  53. FREE(textFile->Sections[u].Name);
  54. }
  55. FREE(textFile->Sections);
  56. }
  57. FREE(textFile);
  58. }
  59. PMYTEXTFILE
  60. ReadRenameFile(
  61. IN PCWSTR DriveRootPath
  62. )
  63. {
  64. NTSTATUS Status;
  65. OBJECT_ATTRIBUTES ObjectAttributes;
  66. UNICODE_STRING UnicodeString;
  67. IO_STATUS_BLOCK IoStatusBlock;
  68. WCHAR FullPath[NTMAXPATH] = {0};
  69. HANDLE Handle;
  70. FILE_STANDARD_INFORMATION FileInfo;
  71. PVOID Buffer;
  72. PWCHAR UnicodeBuffer;
  73. ULONG u;
  74. PMYTEXTFILE p = NULL;
  75. ULONG CharCount;
  76. wcsncpy(FullPath,DriveRootPath,sizeof(FullPath)/sizeof(FullPath[0]) - 1);
  77. ConcatenatePaths(FullPath,WINNT_OEM_LFNLIST_W,NTMAXPATH);
  78. //
  79. // Open the file.
  80. //
  81. INIT_OBJA(&ObjectAttributes,&UnicodeString,FullPath);
  82. Status = NtCreateFile(
  83. &Handle,
  84. FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  85. &ObjectAttributes,
  86. &IoStatusBlock,
  87. NULL,
  88. 0,
  89. FILE_SHARE_READ,
  90. FILE_OPEN,
  91. FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE,
  92. NULL,
  93. 0
  94. );
  95. if(!NT_SUCCESS(Status)) {
  96. KdPrint(("LFN: Unable to open %ws (%x)\n",FullPath,Status));
  97. goto c0;
  98. }
  99. //
  100. // Determine the size of the file.
  101. //
  102. Status = NtQueryInformationFile(
  103. Handle,
  104. &IoStatusBlock,
  105. &FileInfo,
  106. sizeof(FileInfo),
  107. FileStandardInformation
  108. );
  109. if(!NT_SUCCESS(Status)) {
  110. KdPrint(("LFN: Unable to determine size of %ws (%x)\n",FullPath,Status));
  111. goto c1;
  112. }
  113. //
  114. // Allocate a chunk of memory and read the file in.
  115. //
  116. Buffer = MALLOC(FileInfo.EndOfFile.LowPart);
  117. if(!Buffer) {
  118. KdPrint(("LFN: malloc failed\n"));
  119. goto c1;
  120. }
  121. Status = NtReadFile(
  122. Handle,
  123. NULL,
  124. NULL,
  125. NULL,
  126. &IoStatusBlock,
  127. Buffer,
  128. FileInfo.EndOfFile.LowPart,
  129. NULL,
  130. NULL
  131. );
  132. if(!NT_SUCCESS(Status)) {
  133. KdPrint((
  134. "LFN: Unable to read %u bytes from file %ws (%x)\n",
  135. FileInfo.EndOfFile.LowPart,
  136. FullPath,
  137. Status
  138. ));
  139. goto c2;
  140. }
  141. //
  142. // Allocate a buffer for unicode conversion.
  143. // Leave room for a terminating NUL.
  144. //
  145. UnicodeBuffer = MALLOC((FileInfo.EndOfFile.LowPart+1)*sizeof(WCHAR));
  146. if(!UnicodeBuffer) {
  147. KdPrint(("LFN: malloc failed\n"));
  148. goto c2;
  149. }
  150. //
  151. // Convert to unicode.
  152. //
  153. Status = RtlOemToUnicodeN(
  154. UnicodeBuffer,
  155. FileInfo.EndOfFile.LowPart*sizeof(WCHAR),
  156. &CharCount,
  157. Buffer,
  158. FileInfo.EndOfFile.LowPart
  159. );
  160. if(!NT_SUCCESS(Status)) {
  161. KdPrint(("LFN: Unable to convert file data to unicode (%x)\n",Status));
  162. goto c3;
  163. }
  164. CharCount /= sizeof(WCHAR);
  165. //
  166. // Nul-terminate the buffer and change instances of CR and control-z
  167. // to spaces. Also make sure there are no 0 chars in the buffer.
  168. //
  169. for(u=0; u<CharCount; u++) {
  170. if((UnicodeBuffer[u] == 26) || (UnicodeBuffer[u] == L'\r') || !UnicodeBuffer[u]) {
  171. UnicodeBuffer[u] = L' ';
  172. }
  173. }
  174. //
  175. // Allocate a text file structure.
  176. //
  177. p = MALLOC(sizeof(MYTEXTFILE));
  178. if(!p) {
  179. KdPrint(("LFN: malloc failed\n"));
  180. goto c3;
  181. }
  182. RtlZeroMemory(p,sizeof(MYTEXTFILE));
  183. p->Text = UnicodeBuffer;
  184. UnicodeBuffer[CharCount] = 0;
  185. c3:
  186. if(!NT_SUCCESS(Status)) {
  187. FREE(UnicodeBuffer);
  188. }
  189. c2:
  190. FREE(Buffer);
  191. c1:
  192. NtClose(Handle);
  193. c0:
  194. return(NT_SUCCESS(Status) ? p : NULL);
  195. }
  196. BOOLEAN
  197. FindSections(
  198. IN PMYTEXTFILE TextFile
  199. )
  200. {
  201. PWCHAR p,n;
  202. WCHAR Line[2*NTMAXPATH];
  203. PWCHAR e;
  204. PVOID NewArray;
  205. PWCHAR s;
  206. PWSTR SectionName;
  207. for(p=TextFile->Text; GetLine(p,Line,sizeof(Line)/sizeof(WCHAR),&n); p=n) {
  208. //
  209. // If this is a section save it away in a table of section names.
  210. //
  211. if(Line[0] == L'[') {
  212. s = Line+1;
  213. while((*s == L' ') || (*s == L'\t')) {
  214. s++;
  215. }
  216. if(*s == L'\\') {
  217. s++;
  218. }
  219. //
  220. // Find the end, which is either the ] or a nul.
  221. // Strip off trailing spaces.
  222. //
  223. if(e = wcschr(s,L']')) {
  224. *e = 0;
  225. } else {
  226. e = wcschr(s,0);
  227. }
  228. while((*(e-1) == L' ') || (*(e-1) == L'\t')) {
  229. e--;
  230. *e = 0;
  231. }
  232. if(SectionName = MALLOC((wcslen(s)+1)*sizeof(WCHAR))) {
  233. wcscpy(SectionName,s);
  234. if(TextFile->SectionCount == TextFile->SectionArraySize) {
  235. if(TextFile->SectionCount) {
  236. NewArray = REALLOC(TextFile->Sections,(TextFile->SectionCount+10)*sizeof(MYSECTION));
  237. } else {
  238. NewArray = MALLOC(10*sizeof(MYSECTION));
  239. }
  240. if(NewArray) {
  241. TextFile->Sections = NewArray;
  242. TextFile->SectionArraySize += 10;
  243. } else {
  244. FREE(SectionName);
  245. KdPrint(("LFN: malloc failed\n"));
  246. return(FALSE);
  247. }
  248. }
  249. TextFile->Sections[TextFile->SectionCount].Name = SectionName;
  250. TextFile->Sections[TextFile->SectionCount].Data = n;
  251. TextFile->SectionCount++;
  252. } else {
  253. KdPrint(("LFN: malloc failed\n"));
  254. return(FALSE);
  255. }
  256. }
  257. }
  258. //
  259. // Now sort the sections by name.
  260. //
  261. qsort(TextFile->Sections,TextFile->SectionCount,sizeof(MYSECTION),ComparePaths);
  262. return(TRUE);
  263. }
  264. BOOLEAN
  265. GetLineInSection(
  266. IN PWCHAR StartOfLine,
  267. OUT PWSTR LineBuffer,
  268. IN ULONG BufferSizeChars,
  269. OUT PWCHAR *StartOfNextLine
  270. )
  271. {
  272. //
  273. // Get the line and check if we've reached the end of the section.
  274. //
  275. if(!GetLine(StartOfLine,LineBuffer,BufferSizeChars,StartOfNextLine)
  276. || (LineBuffer[0] == L'[')) {
  277. return(FALSE);
  278. }
  279. return(TRUE);
  280. }
  281. BOOLEAN
  282. GetLine(
  283. IN PWCHAR StartOfLine,
  284. OUT PWSTR LineBuffer,
  285. IN ULONG BufferSizeChars,
  286. OUT PWCHAR *StartOfNextLine
  287. )
  288. {
  289. PWCHAR LineEnd;
  290. SIZE_T Count;
  291. while(1) {
  292. //
  293. // Skip space chars.
  294. //
  295. while(*StartOfLine && ((*StartOfLine == L' ') || (*StartOfLine == L'\t'))) {
  296. StartOfLine++;
  297. }
  298. if(*StartOfLine == 0) {
  299. //
  300. // Nothing left.
  301. //
  302. return(FALSE);
  303. }
  304. //
  305. // Find the end of the line, which is either the newline or nul.
  306. //
  307. if(LineEnd = wcschr(StartOfLine,L'\n')) {
  308. *StartOfNextLine = LineEnd+1;
  309. } else {
  310. LineEnd = wcschr(StartOfLine,0);
  311. *StartOfNextLine = LineEnd;
  312. }
  313. //
  314. // Ignore this line if it's a comment or empty.
  315. // Otherwise return it.
  316. //
  317. if((*StartOfLine != L';') && (*StartOfLine != L' ')) {
  318. Count = LineEnd - StartOfLine;
  319. if(Count >= BufferSizeChars) {
  320. Count = BufferSizeChars-1;
  321. }
  322. RtlCopyMemory(LineBuffer,StartOfLine,Count*sizeof(WCHAR));
  323. LineBuffer[Count] = 0;
  324. return(TRUE);
  325. }
  326. StartOfLine = *StartOfNextLine;
  327. }
  328. }
  329. int
  330. __cdecl
  331. ComparePaths(
  332. const void *p1,
  333. const void *p2
  334. )
  335. {
  336. unsigned u1,u2;
  337. PWCHAR s1,s2;
  338. //
  339. // Count \'s in each. The one with fewer is 'greater'.
  340. //
  341. s1 = ((PMYSECTION)p1)->Name;
  342. s2 = ((PMYSECTION)p2)->Name;
  343. u1 = 0;
  344. u2 = 0;
  345. while(*s1) {
  346. if(*s1 == L'\\') {
  347. u1++;
  348. }
  349. s1++;
  350. }
  351. while(*s2) {
  352. if(*s2 == L'\\') {
  353. u2++;
  354. }
  355. s2++;
  356. }
  357. if(u1 == u2) {
  358. return(0);
  359. }
  360. return((u1 < u2) ? 1 : -1);
  361. }
  362. BOOLEAN
  363. ParseLine(
  364. IN OUT PWSTR Line,
  365. OUT PWSTR *LHS,
  366. OUT PWSTR *RHS
  367. )
  368. {
  369. PWCHAR p,q;
  370. //
  371. // We rely on the routines abive to have stripped out
  372. // leading spaces.
  373. //
  374. *LHS = Line;
  375. //
  376. // Find the equals. The LHS isn't allowed to be quoted.
  377. // Strip trailing space off the LHS.
  378. //
  379. p = wcschr(Line,L'=');
  380. if(!p || (p == Line)) {
  381. return(FALSE);
  382. }
  383. q = p+1;
  384. *p-- = 0;
  385. while((*p == L' ') || (*p == L'\t')) {
  386. *p-- = 0;
  387. }
  388. while(*q && ((*q == L' ') || (*q == L'\t'))) {
  389. q++;
  390. }
  391. if(*q == 0) {
  392. return(FALSE);
  393. }
  394. if(*q == L'\"') {
  395. q++;
  396. }
  397. *RHS = q;
  398. p = q + wcslen(q);
  399. p--;
  400. while((*p == L' ') || (*p == L'\t')) {
  401. *p-- = 0;
  402. }
  403. if(*p == L'\"') {
  404. *p = 0;
  405. }
  406. return(TRUE);
  407. }