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.

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