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.

473 lines
8.8 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. delrp.c
  5. This module contains a simple program to blatantly delete a reparse point
  6. of any kind.
  7. Author:
  8. Felipe Cabrera (Cabrera) 11-Jul-1997
  9. Revision History:
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <stdio.h>
  14. #include <stdlib.h> // exit
  15. #include <io.h> // _get_osfhandle
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <ntioapi.h>
  20. #include <windows.h>
  21. #include <locale.h> // setlocale
  22. //
  23. //
  24. // Functions forward referenced.
  25. //
  26. void
  27. SzToWsz (
  28. OUT WCHAR *Unicode,
  29. IN char *Ansi
  30. );
  31. void
  32. ScanArgs (
  33. int argc,
  34. char **argv
  35. );
  36. void
  37. __cdecl
  38. printmessage (
  39. DWORD messageID,
  40. ...
  41. );
  42. void
  43. __cdecl
  44. DisplayMsg (
  45. DWORD MsgNum,
  46. ...
  47. );
  48. int
  49. FileIsConsole (
  50. int fh
  51. );
  52. //
  53. // I/O stream handles and variables.
  54. //
  55. HANDLE hInput;
  56. HANDLE hOutput;
  57. HANDLE hError;
  58. #define STDIN 0
  59. #define STDOUT 1
  60. #define STDERR 2
  61. BOOL ConsoleInput;
  62. BOOL ConsoleOutput;
  63. BOOL ConsoleError;
  64. //
  65. // Core control state vars
  66. //
  67. BOOLEAN NeedHelp;
  68. #include "delrpmsg.h"
  69. TCHAR Buf[1024]; // for displaying stuff
  70. //
  71. // Main
  72. //
  73. void
  74. __cdecl
  75. main(
  76. int argc,
  77. char **argv
  78. )
  79. /*++
  80. Routine Description:
  81. Main procedure for pentnt.
  82. First, we call a series of routines that build a state vector
  83. in some booleans.
  84. We'll then act on these control variables:
  85. NeedHelp - User has asked for help, or made a command error
  86. Arguments:
  87. argc - count of arguments, including the name of our proggram
  88. argv - argument list - see command line syntax above
  89. Return Value:
  90. Exit(0) - the file was deleted
  91. Exit(1) - a problem ocurred.
  92. --*/
  93. {
  94. CHAR lBuf[16];
  95. DWORD dwCodePage;
  96. LANGID LangId;
  97. NTSTATUS Status = STATUS_SUCCESS;
  98. OBJECT_ATTRIBUTES ObjectAttributes;
  99. HANDLE Handle;
  100. UNICODE_STRING UnicodeName;
  101. IO_STATUS_BLOCK IoStatusBlock;
  102. BOOLEAN TranslationStatus;
  103. PVOID FreeBuffer;
  104. FILE_DISPOSITION_INFORMATION Disposition = {TRUE};
  105. WCHAR WFileName[MAX_PATH];
  106. //
  107. // Build up state vector in global booleans.
  108. //
  109. ScanArgs(argc, argv);
  110. //
  111. // printf( "argc = %d NeedHelp = %d\n", argc, NeedHelp );
  112. //
  113. //
  114. // Since FormatMessage checks the current TEB's locale, and the Locale for
  115. // CHCP is initialized when the message class is initialized, the TEB has to
  116. // be updated after the code page is changed successfully.
  117. // Why are we doing this, you ask. Well, the FE guys have plans to add
  118. // more than one set of language resources to this module, but not all
  119. // the possible resources. So this limited set is what they plan for.
  120. // If FormatMessage can't find the right language, it falls back to
  121. // something hopefully useful.
  122. //
  123. dwCodePage = GetConsoleOutputCP();
  124. sprintf(lBuf, ".%d", dwCodePage);
  125. switch( dwCodePage )
  126. {
  127. case 437:
  128. LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
  129. break;
  130. case 932:
  131. LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT );
  132. break;
  133. case 949:
  134. LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN );
  135. break;
  136. case 936:
  137. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );
  138. break;
  139. case 950:
  140. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL );
  141. break;
  142. default:
  143. LangId = MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT );
  144. lBuf[0] = '\0';
  145. break;
  146. }
  147. SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) );
  148. setlocale(LC_ALL, lBuf);
  149. //
  150. // Set the appropriate handles.
  151. //
  152. hInput = GetStdHandle(STD_INPUT_HANDLE);
  153. ConsoleInput = FileIsConsole(STDIN);
  154. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  155. ConsoleOutput = FileIsConsole(STDOUT);
  156. hError = GetStdHandle(STD_ERROR_HANDLE);
  157. ConsoleError = FileIsConsole(STDERR);
  158. //
  159. // OK, we know the state of the command, do work
  160. //
  161. //
  162. // If they asked for help, or did something that indicates they don't
  163. // understand how the program works, print help and exit.
  164. //
  165. if (NeedHelp) {
  166. printmessage( MSG_DELRP_HELP );
  167. exit(1);
  168. }
  169. //
  170. // Change the string to Unicode and pass down to open the file.
  171. //
  172. SzToWsz( WFileName, argv[1] );
  173. TranslationStatus = RtlDosPathNameToNtPathName_U(
  174. WFileName,
  175. &UnicodeName,
  176. NULL,
  177. NULL
  178. );
  179. if (!TranslationStatus) {
  180. printmessage( MSG_DELRP_WRONG_NAME );
  181. exit(1);
  182. }
  183. FreeBuffer = UnicodeName.Buffer;
  184. InitializeObjectAttributes(
  185. &ObjectAttributes,
  186. &UnicodeName,
  187. OBJ_CASE_INSENSITIVE,
  188. NULL,
  189. NULL
  190. );
  191. //
  192. // printf( "Transformed unicode str is %Z\n", &UnicodeName );
  193. //
  194. //
  195. // Open the file for delete access.
  196. // Inhibit the reparse behavior using FILE_OPEN_REPARSE_POINT.
  197. // This will get a handle to the entity whether the appropriate filter is or not in place.
  198. //
  199. Status = NtOpenFile(
  200. &Handle,
  201. (ACCESS_MASK)DELETE,
  202. &ObjectAttributes,
  203. &IoStatusBlock,
  204. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  205. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
  206. );
  207. if (!NT_SUCCESS(Status)) {
  208. SzToWsz( WFileName, argv[1] );
  209. swprintf(&Buf[0], TEXT("%s"), WFileName);
  210. DisplayMsg(MSG_DELRP_OPEN_FAILED_NL, Buf);
  211. // printmessage( MSG_DELRP_OPEN_FAILED );
  212. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  213. exit(1);
  214. }
  215. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  216. //
  217. // Delete the file
  218. //
  219. Status = NtSetInformationFile(
  220. Handle,
  221. &IoStatusBlock,
  222. &Disposition,
  223. sizeof(Disposition),
  224. FileDispositionInformation
  225. );
  226. NtClose(Handle);
  227. if (!NT_SUCCESS(Status)) {
  228. printmessage( MSG_DELRP_DELETE_FAILED );
  229. exit(1);
  230. }
  231. exit(0);
  232. } // main
  233. VOID
  234. ScanArgs(
  235. int argc,
  236. char **argv
  237. )
  238. /*++
  239. Routine Description:
  240. ScanArgs - parse command line arguments, and set control flags
  241. to reflect what we find.
  242. Sets NeedHelp.
  243. Arguments:
  244. argc - count of command line args
  245. argv - argument vector
  246. Return Value:
  247. --*/
  248. {
  249. int i;
  250. NeedHelp = FALSE;
  251. if ((argc == 1) ||
  252. (argc > 3)) {
  253. NeedHelp = TRUE;
  254. goto done;
  255. }
  256. //
  257. // At this point argc == 2
  258. //
  259. if ((argv[1][0] == '/') &&
  260. (argv[1][1] == '?') &&
  261. (strlen(argv[1]) == 2)) {
  262. NeedHelp = TRUE;
  263. goto done;
  264. }
  265. done:
  266. return;
  267. } // ScanArgs
  268. //
  269. // Changing a file name to wide characters.
  270. //
  271. void
  272. SzToWsz (
  273. OUT WCHAR *Unicode,
  274. IN char *Ansi
  275. )
  276. {
  277. while (*Unicode++ = *Ansi++)
  278. ;
  279. return;
  280. } // SzToWsz
  281. //
  282. // Call FormatMessage and dump the result. All messages to Stdout
  283. //
  284. void
  285. __cdecl
  286. printmessage (
  287. DWORD messageID,
  288. ...
  289. )
  290. {
  291. unsigned short messagebuffer[4096];
  292. va_list ap;
  293. va_start(ap, messageID);
  294. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, messageID, 0,
  295. messagebuffer, 4095, &ap);
  296. wprintf(messagebuffer);
  297. va_end(ap);
  298. } // printmessage
  299. TCHAR DisplayBuffer[4096];
  300. CHAR DisplayBuffer2[4096];
  301. void
  302. __cdecl
  303. DisplayMsg (
  304. DWORD MsgNum,
  305. ...
  306. )
  307. {
  308. DWORD len, bytes_written;
  309. BOOL success;
  310. DWORD status;
  311. va_list ap;
  312. va_start(ap, MsgNum);
  313. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MsgNum, 0,
  314. DisplayBuffer, 4096, &ap);
  315. if (ConsoleOutput) {
  316. success = WriteConsole(hOutput, (LPVOID)DisplayBuffer, len,
  317. &bytes_written, NULL);
  318. } else {
  319. CharToOem(DisplayBuffer, DisplayBuffer2);
  320. success = WriteFile(hOutput, (LPVOID)DisplayBuffer2, len,
  321. &bytes_written, NULL);
  322. }
  323. if (!success || bytes_written != len) {
  324. status = GetLastError();
  325. }
  326. va_end(ap);
  327. } // DisplayMsg
  328. int
  329. FileIsConsole(int fh)
  330. {
  331. unsigned htype;
  332. DWORD dwMode;
  333. HANDLE hFile;
  334. hFile = (HANDLE)_get_osfhandle(fh);
  335. htype = GetFileType(hFile);
  336. htype &= ~FILE_TYPE_REMOTE;
  337. if (FILE_TYPE_CHAR == htype) {
  338. switch (fh) {
  339. case STDIN:
  340. hFile = GetStdHandle(STD_INPUT_HANDLE);
  341. break;
  342. case STDOUT:
  343. hFile = GetStdHandle(STD_OUTPUT_HANDLE);
  344. break;
  345. case STDERR:
  346. hFile = GetStdHandle(STD_ERROR_HANDLE);
  347. break;
  348. }
  349. if (GetConsoleMode(hFile, &dwMode)) {
  350. return TRUE;
  351. }
  352. }
  353. return FALSE;
  354. } // FileIsConsole