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.

522 lines
12 KiB

  1. /*****************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1988-1991 **/
  4. /*****************************************************************/
  5. /**** he - HexEdit a file
  6. *
  7. * Wrapper to HexEdit function to allow file (or drive) editting
  8. *
  9. * Written: Ken Reneris
  10. *
  11. */
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <ntdddisk.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <process.h>
  19. #include <windows.h>
  20. #include "hexedit.h"
  21. NTSTATUS fncRead(), fncWrite(), fncWriteDASD();
  22. void EditFile (char *name);
  23. void ReadIni ();
  24. WORD vAttrList, vAttrTitle, vAttrHigh;
  25. VOID __cdecl
  26. main (argc, argv)
  27. USHORT argc;
  28. char *argv[];
  29. {
  30. char *argument = argv[1];
  31. if (argc < 2) {
  32. printf ("he fname\n");
  33. exit (1);
  34. }
  35. ReadIni ();
  36. if ((strncmp(argv[1], "\\\\.\\", 4)) == 0) {
  37. char *cp;
  38. int index;
  39. // Insure there is a backslash on the DosName being opened.
  40. for (cp = argv[1], index = 0; *cp; *cp++, index++) {
  41. // action in for loop
  42. }
  43. cp--;
  44. if (*cp != '\\') {
  45. // Need to add backslash to name.
  46. argument = GlobalAlloc (0,index + 4);
  47. if (!argument) {
  48. printf("Out of memory\n");
  49. exit (1);
  50. }
  51. for (cp = argv[1], index = 0; argument[index] = *cp; *cp++, index++) {
  52. // action in for loop
  53. }
  54. argument[index] = '\\';
  55. argument[index + 1] = '\0';
  56. }
  57. }
  58. EditFile (argument);
  59. }
  60. void
  61. EditFile (
  62. char *name
  63. )
  64. {
  65. FILE_ALIGNMENT_INFORMATION AlignmentInfo;
  66. PDISK_GEOMETRY_EX DiskGeo;
  67. ULONGLONG li;
  68. struct HexEditParm ei;
  69. USHORT rc, rc1, i, l;
  70. PWSTR WideName;
  71. OBJECT_ATTRIBUTES oa;
  72. NTSTATUS status;
  73. UNICODE_STRING NtDriveName;
  74. ANSI_STRING NtDriveNameAnsi;
  75. IO_STATUS_BLOCK status_block;
  76. UCHAR GeoBuf[ 8*1024];
  77. UCHAR Root[12];
  78. //
  79. // Try to open & edit as regular filename
  80. //
  81. memset ((PUCHAR) &ei, 0, sizeof (ei));
  82. ei.ename = name;
  83. ei.flag = FHE_VERIFYONCE | FHE_SAVESCRN | FHE_JUMP;
  84. ei.read = fncRead;
  85. ei.write = fncWrite;
  86. ei.ioalign = 1;
  87. ei.Console = INVALID_HANDLE_VALUE;
  88. ei.AttrNorm = vAttrList;
  89. ei.AttrHigh = vAttrTitle;
  90. ei.AttrReverse = vAttrHigh;
  91. ei.handle = CreateFile (
  92. name,
  93. GENERIC_READ | GENERIC_WRITE,
  94. FILE_SHARE_READ | FILE_SHARE_WRITE,
  95. NULL,
  96. OPEN_EXISTING,
  97. 0,
  98. NULL );
  99. if (ei.handle == INVALID_HANDLE_VALUE) {
  100. // Try for just read access
  101. ei.handle = CreateFile (
  102. name,
  103. GENERIC_READ,
  104. FILE_SHARE_READ | FILE_SHARE_WRITE,
  105. NULL,
  106. OPEN_EXISTING,
  107. 0,
  108. NULL );
  109. }
  110. if (ei.handle != INVALID_HANDLE_VALUE) {
  111. ULONG High = 0;
  112. ei.totlen = 0;
  113. ei.totlen = SetFilePointer (ei.handle, 0, &High, FILE_END);
  114. ei.totlen |= ((ULONGLONG)High) << 32;
  115. HexEdit (&ei);
  116. return;
  117. }
  118. rc = (USHORT)GetLastError ();
  119. //
  120. // Try expanding the name from dosname to ntname.
  121. // Since regular name failed, assume a sector edit
  122. //
  123. l = strlen(name)+1;
  124. WideName = GlobalAlloc (0,l * sizeof(WCHAR));
  125. if (!WideName) {
  126. printf("Out of memory\n");
  127. exit(1);
  128. }
  129. ZeroMemory(WideName, l*sizeof(WCHAR));
  130. for(i=0; i < l; i++)
  131. WideName[i] = name[i];
  132. // OK, now get the corresponding NT name
  133. rc1 = RtlDosPathNameToNtPathName_U (
  134. WideName,
  135. &NtDriveName,
  136. NULL,
  137. NULL );
  138. if (!rc1) {
  139. printf ("Open error %d\n", rc);
  140. exit (rc);
  141. }
  142. // If the NT drive name has a trailing backslash, remove it.
  143. l = NtDriveName.Length/sizeof(WCHAR);
  144. if( NtDriveName.Buffer[l-1] == '\\' ) {
  145. NtDriveName.Buffer[l-1] = 0;
  146. NtDriveName.Length -= sizeof(WCHAR);
  147. }
  148. InitializeObjectAttributes(
  149. &oa,
  150. &NtDriveName,
  151. OBJ_CASE_INSENSITIVE,
  152. 0,
  153. 0 );
  154. status = NtOpenFile(
  155. &ei.handle,
  156. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  157. &oa,
  158. &status_block,
  159. FILE_SHARE_READ | FILE_SHARE_WRITE,
  160. FILE_SYNCHRONOUS_IO_ALERT );
  161. if (!NT_SUCCESS(status)) {
  162. // try for just read access
  163. status = NtOpenFile(
  164. &ei.handle,
  165. SYNCHRONIZE | FILE_READ_DATA,
  166. &oa,
  167. &status_block,
  168. FILE_SHARE_READ | FILE_SHARE_WRITE,
  169. FILE_SYNCHRONOUS_IO_ALERT );
  170. }
  171. if (!NT_SUCCESS(status)) {
  172. NtDriveName.Length = strlen(name) * sizeof(WCHAR);
  173. NtDriveName.Buffer = WideName;
  174. InitializeObjectAttributes(
  175. &oa,
  176. &NtDriveName,
  177. OBJ_CASE_INSENSITIVE,
  178. 0,
  179. 0 );
  180. status = NtOpenFile(
  181. &ei.handle,
  182. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  183. &oa,
  184. &status_block,
  185. FILE_SHARE_READ | FILE_SHARE_WRITE,
  186. FILE_SYNCHRONOUS_IO_ALERT );
  187. if (!NT_SUCCESS(status)) {
  188. // try for just read access
  189. status = NtOpenFile(
  190. &ei.handle,
  191. SYNCHRONIZE | FILE_READ_DATA,
  192. &oa,
  193. &status_block,
  194. FILE_SHARE_READ | FILE_SHARE_WRITE,
  195. FILE_SYNCHRONOUS_IO_ALERT );
  196. }
  197. }
  198. RtlUnicodeStringToAnsiString (&NtDriveNameAnsi, &NtDriveName, TRUE);
  199. ei.ename = NtDriveNameAnsi.Buffer;
  200. if (!NT_SUCCESS(status)) {
  201. printf ("%s open error %lx\n", ei.ename, status);
  202. exit (status);
  203. }
  204. /*
  205. NtQueryInformationFile(
  206. ei.handle,
  207. &status_block,
  208. &AlignmentInfo,
  209. sizeof( AlignmentInfo ),
  210. FileAlignmentInformation );
  211. ei.ioalign = AlignmentInfo.AlignmentRequirement;
  212. */
  213. ei.ioalign = 0;
  214. ei.totlen = 0;
  215. if (NtDriveNameAnsi.Buffer[ NtDriveNameAnsi.Length - 1] == ':') {
  216. sprintf( Root, "%c:\\", NtDriveNameAnsi.Buffer[ NtDriveNameAnsi.Length - 2]);
  217. //
  218. // For non-cdrom drive letter opens, we need to use
  219. // get partition info, not get disk info, for the partition size.
  220. //
  221. if (DRIVE_CDROM != GetDriveType( Root)) {
  222. PPARTITION_INFORMATION Part = (PVOID)GeoBuf;
  223. status = NtDeviceIoControlFile(
  224. ei.handle,
  225. 0,
  226. NULL,
  227. NULL,
  228. &status_block,
  229. IOCTL_DISK_GET_PARTITION_INFO,
  230. NULL,
  231. 0,
  232. GeoBuf,
  233. sizeof( GeoBuf) );
  234. if (NT_SUCCESS(status)) {
  235. ei.totlen = Part->PartitionLength.QuadPart;
  236. }
  237. }
  238. }
  239. //
  240. // Get sectorsize and, if we haven't got it already, disk/partition size
  241. //
  242. status = NtDeviceIoControlFile( ei.handle,
  243. 0,
  244. NULL,
  245. NULL,
  246. &status_block,
  247. IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
  248. NULL,
  249. 0,
  250. GeoBuf,
  251. sizeof( GeoBuf) );
  252. if (NT_SUCCESS(status)) {
  253. DiskGeo = (PVOID)GeoBuf;
  254. if (ei.ioalign < DiskGeo->Geometry.BytesPerSector) {
  255. ei.ioalign = DiskGeo->Geometry.BytesPerSector;
  256. }
  257. if (0 == ei.totlen) {
  258. ei.totlen = DiskGeo->DiskSize.QuadPart;
  259. }
  260. }
  261. else {
  262. //
  263. // The EX call failed, try the old one. GPT discs seem
  264. // to fail the EX call.
  265. //
  266. PDISK_GEOMETRY OldGeo;
  267. status = NtDeviceIoControlFile( ei.handle,
  268. 0,
  269. NULL,
  270. NULL,
  271. &status_block,
  272. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  273. NULL,
  274. 0,
  275. GeoBuf,
  276. sizeof( GeoBuf) );
  277. if (NT_SUCCESS(status)) {
  278. OldGeo = (PVOID)GeoBuf;
  279. if (ei.ioalign < OldGeo->BytesPerSector) {
  280. ei.ioalign = OldGeo->BytesPerSector;
  281. }
  282. if (0 == ei.totlen) {
  283. ei.totlen = OldGeo->Cylinders.QuadPart * OldGeo->BytesPerSector *
  284. OldGeo->SectorsPerTrack * OldGeo->TracksPerCylinder;
  285. }
  286. }
  287. }
  288. //
  289. // Last resort for partition/disk size.
  290. //
  291. if (0 == ei.totlen) {
  292. ULONG High = 0;
  293. if (ei.ioalign < 0x200) {
  294. ei.ioalign = 0x200;
  295. }
  296. ei.totlen = 0;
  297. ei.totlen = SetFilePointer (ei.handle, 0, &High, FILE_END);
  298. ei.totlen |= ((ULONGLONG)High) << 32;
  299. }
  300. //
  301. // If a filesystem is mounted, we need to enable extended
  302. // DASD io in order to read the whole volume. Ignore result,
  303. // not all FSs support it.
  304. //
  305. status = NtDeviceIoControlFile(
  306. ei.handle,
  307. 0,
  308. NULL,
  309. NULL,
  310. &status_block,
  311. FSCTL_ALLOW_EXTENDED_DASD_IO,
  312. NULL,
  313. 0,
  314. NULL,
  315. 0);
  316. ei.flag = FHE_VERIFYALL | FHE_PROMPTSEC | FHE_SAVESCRN | FHE_JUMP;
  317. HexEdit (&ei);
  318. }
  319. NTSTATUS fncRead (h, loc, data, len)
  320. HANDLE h;
  321. DWORD len;
  322. ULONGLONG loc;
  323. char *data;
  324. {
  325. DWORD l, br;
  326. ULONG High = (ULONG)(loc >> 32);
  327. l = SetFilePointer (h, (ULONG)loc, &High, FILE_BEGIN);
  328. if (l == -1)
  329. return GetLastError();
  330. if (!ReadFile (h, data, len, &br, NULL))
  331. return GetLastError();
  332. return (br != len ? ERROR_READ_FAULT : 0);
  333. }
  334. NTSTATUS fncWrite (h, loc, data, len)
  335. HANDLE h;
  336. DWORD len;
  337. ULONGLONG loc;
  338. char *data;
  339. {
  340. DWORD l, bw;
  341. ULONG High = (ULONG)(loc >> 32);
  342. l = SetFilePointer (h, (ULONG)loc, &High, FILE_BEGIN);
  343. if (l == -1)
  344. return GetLastError();
  345. if (!WriteFile (h, data, len, &bw, NULL))
  346. return GetLastError();
  347. return (bw != len ? ERROR_WRITE_FAULT : 0);
  348. }
  349. /*** xtoi - Hex to int
  350. *
  351. * Entry:
  352. * pt - pointer to hex number
  353. *
  354. * Return:
  355. * value of hex number
  356. *
  357. */
  358. unsigned xtoi (pt)
  359. char *pt;
  360. {
  361. unsigned u;
  362. char c;
  363. u = 0;
  364. while (c = *(pt++)) {
  365. if (c >= 'a' && c <= 'f')
  366. c -= 'a' - 'A';
  367. if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
  368. u = u << 4 | c - (c >= 'A' ? 'A'-10 : '0');
  369. }
  370. return (u);
  371. }
  372. void
  373. ReadIni ()
  374. {
  375. static char Delim[] = " :=;\t\r\n";
  376. FILE *fp;
  377. char *env, *verb, *value;
  378. char s [200];
  379. long l;
  380. env = getenv ("INIT");
  381. if (env == NULL)
  382. return;
  383. if ((strlen(env) + sizeof ("\\TOOLS.INI") + 1) > sizeof(s))
  384. return;
  385. strcpy (s, env);
  386. strcat (s, "\\TOOLS.INI"); // just use list ini section
  387. fp = fopen (s, "r");
  388. if (fp == NULL)
  389. return;
  390. while (fgets (s, 200, fp) != NULL) {
  391. if (s[0] != '[')
  392. continue;
  393. _strupr (s);
  394. if (strstr (s, "LIST") == NULL)
  395. continue;
  396. /*
  397. * ini file found w/ "list" keyword. Now read it.
  398. */
  399. while (fgets (s, 200, fp) != NULL) {
  400. if (s[0] == '[')
  401. break;
  402. verb = strtok (s, Delim);
  403. value = strtok (NULL, Delim);
  404. if (verb == NULL)
  405. continue;
  406. if (value == NULL)
  407. value = "";
  408. _strupr (verb);
  409. if (strcmp (verb, "LCOLOR") == 0) vAttrList = (WORD)xtoi(value);
  410. else if (strcmp (verb, "TCOLOR") == 0) vAttrTitle= (WORD)xtoi(value);
  411. else if (strcmp (verb, "HCOLOR") == 0) vAttrHigh = (WORD)xtoi(value);
  412. }
  413. break;
  414. }
  415. fclose (fp);
  416. }