Source code of Windows XP (NT5)
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.

543 lines
15 KiB

  1. /*++
  2. Copyright (c) 1993-1994 Microsoft Corporation
  3. Module Name:
  4. fileutl.c
  5. Abstract:
  6. Routines for getting data from ini file
  7. Author:
  8. HonWah Chan (a-honwah) October, 1993
  9. Revision History:
  10. --*/
  11. #include "initodat.h"
  12. #include "strids.h"
  13. #include "common.h"
  14. #include "winerror.h"
  15. NTSTATUS
  16. DatReadMultiSzFile(
  17. #ifdef FE_SB
  18. IN UINT uCodePage,
  19. #endif
  20. IN PUNICODE_STRING FileName,
  21. OUT PVOID *ValueBuffer,
  22. OUT PULONG ValueLength
  23. )
  24. {
  25. NTSTATUS Status;
  26. UNICODE_STRING NtFileName;
  27. PWSTR s;
  28. UNICODE_STRING MultiSource;
  29. UNICODE_STRING MultiValue;
  30. REG_UNICODE_FILE MultiSzFile;
  31. ULONG MultiSzFileSize;
  32. if (ValueBuffer == NULL || ValueLength == NULL) {
  33. return STATUS_INVALID_PARAMETER;
  34. }
  35. FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL;
  36. RtlDosPathNameToNtPathName_U( FileName->Buffer,
  37. &NtFileName,
  38. NULL,
  39. NULL );
  40. #ifdef FE_SB
  41. Status = DatLoadAsciiFileAsUnicode( uCodePage, &NtFileName, &MultiSzFile );
  42. #else
  43. Status = DatLoadAsciiFileAsUnicode( &NtFileName, &MultiSzFile );
  44. #endif
  45. if (!NT_SUCCESS( Status )) {
  46. return( Status );
  47. }
  48. MultiSzFileSize = (ULONG)(MultiSzFile.EndOfFile -
  49. MultiSzFile.NextLine) * sizeof(WCHAR);
  50. *ValueLength = 0;
  51. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  52. MultiSzFileSize);
  53. if (* ValueBuffer == NULL) {
  54. return STATUS_NO_MEMORY;
  55. }
  56. MultiSource.Buffer = MultiSzFile.NextLine;
  57. if (MultiSzFileSize <= MAXUSHORT) {
  58. MultiSource.Length =
  59. MultiSource.MaximumLength = (USHORT)MultiSzFileSize;
  60. } else {
  61. MultiSource.Length =
  62. MultiSource.MaximumLength = MAXUSHORT;
  63. }
  64. while (DatGetMultiString(&MultiSource, &MultiValue)) {
  65. RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength,
  66. MultiValue.Buffer,
  67. MultiValue.Length );
  68. *ValueLength += MultiValue.Length;
  69. s = MultiSource.Buffer;
  70. while ( *s != L'"' &&
  71. *s != L',' &&
  72. ((s - MultiSource.Buffer) * sizeof(WCHAR)) <
  73. MultiSource.Length ) s++;
  74. if ( ((s - MultiSource.Buffer) * sizeof(WCHAR)) ==
  75. MultiSource.Length ||
  76. *s == L',' ||
  77. *s == L';' ) {
  78. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] =
  79. UNICODE_NULL;
  80. *ValueLength += sizeof(UNICODE_NULL);
  81. if ( *s == L';' ) {
  82. break;
  83. }
  84. }
  85. if ( (MultiSzFile.EndOfFile - MultiSource.Buffer) * sizeof(WCHAR) >=
  86. MAXUSHORT ) {
  87. MultiSource.Length =
  88. MultiSource.MaximumLength = MAXUSHORT;
  89. } else {
  90. MultiSource.Length =
  91. MultiSource.MaximumLength =
  92. (USHORT)((MultiSzFile.EndOfFile - MultiSource.Buffer) *
  93. sizeof(WCHAR));
  94. }
  95. }
  96. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL;
  97. *ValueLength += sizeof(UNICODE_NULL);
  98. // Virtual memory for reading of MultiSzFile freed at process
  99. // death?
  100. return( TRUE );
  101. }
  102. NTSTATUS
  103. DatLoadAsciiFileAsUnicode(
  104. #ifdef FE_SB
  105. IN UINT uCodePage,
  106. #endif
  107. IN PUNICODE_STRING FileName,
  108. OUT PREG_UNICODE_FILE UnicodeFile
  109. )
  110. {
  111. NTSTATUS Status;
  112. OBJECT_ATTRIBUTES ObjectAttributes;
  113. IO_STATUS_BLOCK IoStatus;
  114. HANDLE File;
  115. FILE_BASIC_INFORMATION FileDateTimeInfo;
  116. FILE_STANDARD_INFORMATION FileInformation;
  117. SIZE_T BufferSize;
  118. ULONG i, i1, LineCount;
  119. PVOID BufferBase;
  120. PCHAR Src = NULL;
  121. PCHAR Src1;
  122. PWSTR Dst = NULL;
  123. memset (&FileDateTimeInfo, 0, sizeof(FileDateTimeInfo));
  124. InitializeObjectAttributes( &ObjectAttributes,
  125. FileName,
  126. OBJ_CASE_INSENSITIVE,
  127. (HANDLE)NULL,
  128. NULL
  129. );
  130. Status = NtOpenFile( &File,
  131. SYNCHRONIZE | GENERIC_READ,
  132. &ObjectAttributes,
  133. &IoStatus,
  134. FILE_SHARE_DELETE |
  135. FILE_SHARE_READ |
  136. FILE_SHARE_WRITE,
  137. FILE_SYNCHRONOUS_IO_NONALERT |
  138. FILE_NON_DIRECTORY_FILE
  139. );
  140. if (!NT_SUCCESS( Status )) {
  141. return( Status );
  142. }
  143. Status = NtQueryInformationFile( File,
  144. &IoStatus,
  145. (PVOID)&FileInformation,
  146. sizeof( FileInformation ),
  147. FileStandardInformation
  148. );
  149. if (NT_SUCCESS( Status )) {
  150. if (FileInformation.EndOfFile.HighPart) {
  151. Status = STATUS_BUFFER_OVERFLOW;
  152. }
  153. }
  154. if (!NT_SUCCESS( Status )) {
  155. NtClose( File );
  156. return( Status );
  157. }
  158. #ifdef FE_SB
  159. BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR ) * 2;
  160. #else
  161. BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR );
  162. #endif
  163. BufferSize += sizeof( UNICODE_NULL );
  164. BufferBase = NULL;
  165. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  166. (PVOID *)&BufferBase,
  167. 0,
  168. &BufferSize,
  169. MEM_COMMIT,
  170. PAGE_READWRITE
  171. );
  172. if (NT_SUCCESS( Status )) {
  173. Src = (PCHAR)BufferBase + ((FileInformation.EndOfFile.LowPart+1) & ~1);
  174. Dst = (PWSTR)BufferBase;
  175. Status = NtReadFile( File,
  176. NULL,
  177. NULL,
  178. NULL,
  179. &IoStatus,
  180. Src,
  181. FileInformation.EndOfFile.LowPart,
  182. NULL,
  183. NULL
  184. );
  185. if (NT_SUCCESS( Status )) {
  186. Status = IoStatus.Status;
  187. if (NT_SUCCESS( Status )) {
  188. if (IoStatus.Information != FileInformation.EndOfFile.LowPart) {
  189. Status = STATUS_END_OF_FILE;
  190. }
  191. else {
  192. Status = NtQueryInformationFile( File,
  193. &IoStatus,
  194. (PVOID)&FileDateTimeInfo,
  195. sizeof( FileDateTimeInfo ),
  196. FileBasicInformation
  197. );
  198. }
  199. }
  200. }
  201. if (!NT_SUCCESS( Status )) {
  202. NtFreeVirtualMemory( NtCurrentProcess(),
  203. (PVOID *)&BufferBase,
  204. &BufferSize,
  205. MEM_RELEASE
  206. );
  207. }
  208. }
  209. NtClose( File );
  210. if (!NT_SUCCESS( Status )) {
  211. return( Status );
  212. }
  213. i = 0;
  214. while (i < FileInformation.EndOfFile.LowPart) {
  215. if (i > 1 && (Src[-2] == ' ' || Src[-2] == '\t') &&
  216. Src[-1] == '\\' && (*Src == '\r' || *Src == '\n')
  217. ) {
  218. if (Dst[-1] == L'\\') {
  219. --Dst;
  220. }
  221. while (Dst > (PWSTR)BufferBase) {
  222. if (Dst[-1] > L' ') {
  223. break;
  224. }
  225. Dst--;
  226. }
  227. LineCount = 0;
  228. while (i < FileInformation.EndOfFile.LowPart) {
  229. if (*Src == '\n') {
  230. i++;
  231. Src++;
  232. LineCount++;
  233. }
  234. else
  235. if (*Src == '\r' &&
  236. (i+1) < FileInformation.EndOfFile.LowPart &&
  237. Src[ 1 ] == '\n'
  238. ) {
  239. i += 2;
  240. Src += 2;
  241. LineCount++;
  242. }
  243. else {
  244. break;
  245. }
  246. }
  247. if (LineCount > 1) {
  248. *Dst++ = L'\n';
  249. }
  250. else {
  251. *Dst++ = L' ';
  252. while (i < FileInformation.EndOfFile.LowPart && (*Src == ' ' || *Src == '\t')) {
  253. i++;
  254. Src++;
  255. }
  256. }
  257. if (i >= FileInformation.EndOfFile.LowPart) {
  258. break;
  259. }
  260. }
  261. else
  262. if ((*Src == '\r' && Src[1] == '\n') || *Src == '\n') {
  263. #pragma warning ( disable : 4127 )
  264. while (TRUE) {
  265. while (i < FileInformation.EndOfFile.LowPart && (*Src == '\r' || *Src == '\n')) {
  266. i++;
  267. Src++;
  268. }
  269. Src1 = Src;
  270. i1 = i;
  271. while (i1 < FileInformation.EndOfFile.LowPart && (*Src1 == ' ' || *Src1 == '\t')) {
  272. i1++;
  273. Src1++;
  274. }
  275. if (i1 < FileInformation.EndOfFile.LowPart &&
  276. (*Src1 == '\r' && Src1[1] == '\n') || *Src1 == '\n'
  277. ) {
  278. Src = Src1;
  279. i = i1;
  280. }
  281. else {
  282. break;
  283. }
  284. }
  285. #pragma warning ( default : 4127 )
  286. *Dst++ = L'\n';
  287. }
  288. else {
  289. #ifdef FE_SB
  290. WCHAR UnicodeCharacter;
  291. LONG cbCharSize = IsDBCSLeadByteEx(uCodePage,*Src) ? 2 : 1;
  292. if ( MultiByteToWideChar(
  293. uCodePage,
  294. 0,
  295. Src,
  296. cbCharSize,
  297. &UnicodeCharacter,
  298. 1) == 0) {
  299. //
  300. // Check for error - The only time this will happen is if there is
  301. // a leadbyte without a trail byte.
  302. //
  303. UnicodeCharacter = 0x0020;
  304. }
  305. i += cbCharSize;
  306. Src += cbCharSize;
  307. *Dst++ = UnicodeCharacter;
  308. #else
  309. i++;
  310. *Dst++ = RtlAnsiCharToUnicodeChar( &Src );
  311. #endif
  312. }
  313. }
  314. if (NT_SUCCESS( Status )) {
  315. *Dst = UNICODE_NULL;
  316. UnicodeFile->FileContents = BufferBase;
  317. UnicodeFile->EndOfFile = Dst;
  318. UnicodeFile->BeginLine = NULL;
  319. UnicodeFile->EndOfLine = NULL;
  320. UnicodeFile->NextLine = BufferBase;
  321. UnicodeFile->LastWriteTime = FileDateTimeInfo.LastWriteTime;
  322. }
  323. else {
  324. NtFreeVirtualMemory( NtCurrentProcess(),
  325. (PVOID *)&BufferBase,
  326. &BufferSize,
  327. MEM_RELEASE
  328. );
  329. }
  330. return( Status );
  331. }
  332. //
  333. // Define an upcase macro for temporary use by the upcase routines
  334. //
  335. #define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
  336. BOOLEAN
  337. DatGetMultiString(
  338. IN OUT PUNICODE_STRING ValueString,
  339. OUT PUNICODE_STRING MultiString
  340. )
  341. /*++
  342. Routine Description:
  343. This routine parses multi-strings of the form
  344. "foo" "bar" "bletch"
  345. Each time it is called, it strips the first string in quotes from
  346. the input string, and returns it as the multi-string.
  347. INPUT ValueString: "foo" "bar" "bletch"
  348. OUTPUT ValueString: "bar" "bletch"
  349. MultiString: foo
  350. Arguments:
  351. ValueString - Supplies the string from which the multi-string will be
  352. parsed
  353. - Returns the remaining string after the multi-string is
  354. removed
  355. MultiString - Returns the multi-string removed from ValueString
  356. Return Value:
  357. TRUE - multi-string found and removed.
  358. FALSE - no more multi-strings remaining.
  359. --*/
  360. {
  361. //
  362. // Find the first quote mark.
  363. //
  364. while ((*(ValueString->Buffer) != L'"') &&
  365. (ValueString->Length > 0)) {
  366. ++ValueString->Buffer;
  367. ValueString->Length -= sizeof(WCHAR);
  368. ValueString->MaximumLength -= sizeof(WCHAR);
  369. }
  370. if (ValueString->Length == 0) {
  371. return(FALSE);
  372. }
  373. //
  374. // We have found the start of the multi-string. Now find the end,
  375. // building up our return MultiString as we go.
  376. //
  377. ++ValueString->Buffer;
  378. ValueString->Length -= sizeof(WCHAR);
  379. ValueString->MaximumLength -= sizeof(WCHAR);
  380. MultiString->Buffer = ValueString->Buffer;
  381. MultiString->Length = 0;
  382. MultiString->MaximumLength = 0;
  383. while ((*(ValueString->Buffer) != L'"') &&
  384. (ValueString->Length > 0)) {
  385. ++ValueString->Buffer;
  386. ValueString->Length -= sizeof(WCHAR);
  387. ValueString->MaximumLength -= sizeof(WCHAR);
  388. MultiString->Length += sizeof(WCHAR);
  389. MultiString->MaximumLength += sizeof(WCHAR);
  390. }
  391. if (ValueString->Length == 0) {
  392. return(FALSE);
  393. }
  394. ++ValueString->Buffer;
  395. ValueString->Length -= sizeof(WCHAR);
  396. ValueString->MaximumLength -= sizeof(WCHAR);
  397. return( TRUE );
  398. }
  399. #define EXTENSION_DELIMITER TEXT('.')
  400. LPTSTR
  401. FindFileExtension (
  402. IN PUNICODE_STRING FileName
  403. )
  404. {
  405. LPTSTR lpszDelimiter ;
  406. lpszDelimiter = _tcsrchr ((LPCTSTR)FileName->Buffer, (TCHAR)EXTENSION_DELIMITER) ;
  407. if (lpszDelimiter)
  408. return lpszDelimiter;
  409. else
  410. return (LPTSTR)((PBYTE)FileName->Buffer + FileName->Length - sizeof(WCHAR));
  411. }
  412. BOOL
  413. OutputIniData (
  414. IN PUNICODE_STRING FileName,
  415. IN LPTSTR OutFileCandidate,
  416. IN PVOID pValueBuffer,
  417. IN ULONG ValueLength
  418. )
  419. {
  420. HANDLE hOutFile = NULL;
  421. LPTSTR lpExtension = NULL;
  422. DWORD nAmtWritten ;
  423. BOOL bSuccess ;
  424. DWORD ErrorCode ;
  425. // If output file not specified, derive from input file name
  426. if (! lstrcmp(OutFileCandidate, (LPCWSTR)L"\0")) {
  427. lpExtension = FindFileExtension (FileName);
  428. lstrcpy (lpExtension, (LPCTSTR)TEXT(".dat"));
  429. lstrcpy (OutFileCandidate, FileName->Buffer);
  430. }
  431. hOutFile = (HANDLE) CreateFile (
  432. OutFileCandidate,
  433. GENERIC_READ | GENERIC_WRITE,
  434. FILE_SHARE_READ,
  435. NULL, CREATE_ALWAYS,
  436. FILE_ATTRIBUTE_NORMAL, NULL);
  437. if ((hOutFile == NULL) || (hOutFile == INVALID_HANDLE_VALUE)) {
  438. ErrorCode = GetLastError();
  439. printf (GetFormatResource(LC_CANT_CREATE), ErrorCode);
  440. if (ErrorCode == ERROR_ACCESS_DENIED)
  441. printf ("%ws\n", GetStringResource(LC_ACCESS_DENIED));
  442. return FALSE;
  443. }
  444. bSuccess = WriteFile (
  445. hOutFile,
  446. pValueBuffer,
  447. ValueLength,
  448. &nAmtWritten,
  449. NULL) ;
  450. bSuccess = bSuccess && (nAmtWritten == ValueLength) ;
  451. CloseHandle( hOutFile );
  452. if (!bSuccess) {
  453. ErrorCode = GetLastError();
  454. printf (GetFormatResource(LC_CANT_WRITE), ErrorCode);
  455. if (ErrorCode == ERROR_DISK_FULL)
  456. printf ("%ws\n", GetStringResource(LC_DISK_FULL));
  457. }
  458. return bSuccess;
  459. }