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.

569 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. devmap.c
  5. Abstract:
  6. Program to launch a command with a different device mapping.
  7. Author:
  8. 02-Oct-1996 Steve Wood (stevewo)
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <windows.h>
  17. UCHAR DeviceNames[ 4096 ];
  18. UCHAR TargetPath[ 4096 ];
  19. typedef struct _DEVICE_LINK {
  20. PCHAR LinkName;
  21. ULONG LinkTargetLength;
  22. PCHAR LinkTarget;
  23. BOOL ProtectedDevice;
  24. BOOL RemoveDevice;
  25. } DEVICE_LINK, *PDEVICE_LINK;
  26. ULONG NumberOfDriveLetters;
  27. ULONG NumberOfDevices;
  28. DEVICE_LINK DriveLetters[ 128 ];
  29. DEVICE_LINK Devices[ 128 ];
  30. BOOLEAN CreatePermanentPrivilegeEnabled;
  31. BOOLEAN CreatePermanentPrivilegeWasEnabled;
  32. BOOLEAN
  33. EnableCreatePermanentPrivilege( void )
  34. {
  35. NTSTATUS Status;
  36. //
  37. // Try to enable create permanent privilege
  38. //
  39. Status = RtlAdjustPrivilege( SE_CREATE_PERMANENT_PRIVILEGE,
  40. TRUE, // Enable
  41. FALSE, // Not impersonating
  42. &CreatePermanentPrivilegeWasEnabled // previous state
  43. );
  44. if (!NT_SUCCESS( Status )) {
  45. return FALSE;
  46. }
  47. CreatePermanentPrivilegeEnabled = TRUE;
  48. return TRUE;
  49. }
  50. void
  51. DisableCreatePermanentPrivilege( void )
  52. {
  53. //
  54. // Restore privileges to what they were
  55. //
  56. RtlAdjustPrivilege( SE_CREATE_PERMANENT_PRIVILEGE,
  57. CreatePermanentPrivilegeWasEnabled,
  58. FALSE,
  59. &CreatePermanentPrivilegeWasEnabled
  60. );
  61. CreatePermanentPrivilegeEnabled = FALSE;
  62. return;
  63. }
  64. void
  65. Usage( void )
  66. {
  67. fprintf( stderr, "usage: DEVMAP [-R]\n" );
  68. fprintf( stderr, " [-r \"device list\"]\n" );
  69. fprintf( stderr, " [-a \"device list\"]\n" );
  70. fprintf( stderr, " command line...\n" );
  71. fprintf( stderr, "where: -R - removes all device definitions\n" );
  72. fprintf( stderr, " -r - removes specified device definitions\n" );
  73. fprintf( stderr, " -a - adds specified device definitions\n" );
  74. fprintf( stderr, " \"device list\" - is a list of one or more blank separated\n" );
  75. fprintf( stderr, " defintions of the form name[=target]\n" );
  76. fprintf( stderr, " If target is not specified for -a then\n" );
  77. fprintf( stderr, " uses the target in effect when DEVMAP\n" );
  78. fprintf( stderr, "\n" );
  79. fprintf( stderr, "Examples:\n" );
  80. fprintf( stderr, "\n" );
  81. fprintf( stderr, " DEVMAP -R -a \"C: D: NUL\" CMD.EXE\n" );
  82. fprintf( stderr, " DEVMAP -r \"UNC\" CMD.EXE\n" );
  83. fprintf( stderr, " DEVMAP -a \"COM1=\\Device\\Serial8\" CMD.EXE\n" );
  84. exit( 1 );
  85. }
  86. void
  87. DisplayDeviceTarget(
  88. char *Msg,
  89. char *Name,
  90. char *Target,
  91. DWORD cchTarget
  92. );
  93. void
  94. DisplayDeviceTarget(
  95. char *Msg,
  96. char *Name,
  97. char *Target,
  98. DWORD cchTarget
  99. )
  100. {
  101. char *s;
  102. printf( "%s%s = ", Msg, Name );
  103. s = Target;
  104. while (*s && cchTarget != 0) {
  105. if (s > Target) {
  106. printf( " ; " );
  107. }
  108. printf( "%s", s );
  109. while (*s++) {
  110. if (!cchTarget--) {
  111. cchTarget = 0;
  112. break;
  113. }
  114. }
  115. }
  116. }
  117. PDEVICE_LINK
  118. FindDevice(
  119. LPSTR Name,
  120. BOOL fAdd
  121. )
  122. {
  123. DWORD i;
  124. LPSTR NewTarget;
  125. PDEVICE_LINK p;
  126. if (fAdd) {
  127. NewTarget = strchr( Name, '=' );
  128. if (NewTarget != NULL) {
  129. *NewTarget++ = '\0';
  130. }
  131. }
  132. for (i=0; i<NumberOfDriveLetters; i++) {
  133. p = &DriveLetters[ i ];
  134. if (!_stricmp( p->LinkName, Name )) {
  135. if (fAdd && NewTarget) {
  136. p->LinkTargetLength = strlen( NewTarget ) + 2;
  137. p->LinkTarget = calloc( 1, p->LinkTargetLength );
  138. if (!p->LinkTarget) {
  139. return NULL;
  140. }
  141. strcpy( p->LinkTarget, NewTarget );
  142. }
  143. return p;
  144. }
  145. }
  146. for (i=0; i<NumberOfDevices; i++) {
  147. p = &Devices[ i ];
  148. if (!_stricmp( p->LinkName, Name )) {
  149. if (fAdd && NewTarget) {
  150. p->LinkTargetLength = strlen( NewTarget ) + 2;
  151. p->LinkTarget = calloc( 1, p->LinkTargetLength );
  152. if (!p->LinkTarget) {
  153. return NULL;
  154. }
  155. strcpy( p->LinkTarget, NewTarget );
  156. }
  157. return p;
  158. }
  159. }
  160. if (fAdd) {
  161. if (NewTarget != NULL) {
  162. if (strlen( Name ) == 2 && Name[1] == ':') {
  163. p = &DriveLetters[ NumberOfDriveLetters++ ];
  164. }
  165. else {
  166. p = &Devices[ NumberOfDevices++ ];
  167. }
  168. p->LinkName = Name;
  169. p->LinkTargetLength = strlen( NewTarget ) + 2;
  170. p->LinkTarget = calloc( 1, p->LinkTargetLength );
  171. if (!p->LinkTarget) {
  172. return NULL;
  173. }
  174. strcpy( p->LinkTarget, NewTarget );
  175. }
  176. else {
  177. fprintf( stderr, "DEVMAP: Unable to add '%s' device name without target.\n", Name );
  178. }
  179. }
  180. else {
  181. fprintf( stderr, "DEVMAP: Unable to remove '%s' device name.\n", Name );
  182. }
  183. return NULL;
  184. }
  185. BOOL
  186. CreateSymbolicLink(
  187. HANDLE DirectoryHandle,
  188. LPSTR Name,
  189. LPSTR Target,
  190. DWORD cchTarget,
  191. BOOL fVerbose
  192. )
  193. {
  194. NTSTATUS Status;
  195. ANSI_STRING AnsiString;
  196. UNICODE_STRING LinkName, LinkTarget;
  197. OBJECT_ATTRIBUTES ObjectAttributes;
  198. HANDLE LinkHandle;
  199. RtlInitAnsiString( &AnsiString, Name );
  200. RtlAnsiStringToUnicodeString( &LinkName, &AnsiString, TRUE );
  201. AnsiString.Buffer = Target;
  202. AnsiString.Length = (USHORT)cchTarget - 2;
  203. AnsiString.MaximumLength = (USHORT)(cchTarget - 1);
  204. RtlAnsiStringToUnicodeString( &LinkTarget, &AnsiString, TRUE );
  205. InitializeObjectAttributes( &ObjectAttributes,
  206. &LinkName,
  207. CreatePermanentPrivilegeEnabled ? OBJ_PERMANENT : 0,
  208. DirectoryHandle,
  209. NULL
  210. );
  211. Status = NtCreateSymbolicLinkObject( &LinkHandle,
  212. SYMBOLIC_LINK_ALL_ACCESS,
  213. &ObjectAttributes,
  214. &LinkTarget
  215. );
  216. if (NT_SUCCESS( Status )) {
  217. if (CreatePermanentPrivilegeEnabled) {
  218. NtClose( LinkHandle );
  219. }
  220. return TRUE;
  221. }
  222. else {
  223. if (fVerbose) {
  224. printf( " (*** FAILED %x ***)", Status );
  225. }
  226. return FALSE;
  227. }
  228. }
  229. int
  230. __cdecl
  231. CompareDeviceLink(
  232. void const *p1,
  233. void const *p2
  234. )
  235. {
  236. return _stricmp( ((PDEVICE_LINK)p1)->LinkName, ((PDEVICE_LINK)p2)->LinkName );
  237. }
  238. int
  239. __cdecl
  240. main(
  241. int argc,
  242. char *argv[]
  243. )
  244. {
  245. DWORD cch, i;
  246. char c, *s;
  247. BOOL fVerbose;
  248. BOOL fRemoveAllDevices;
  249. LPSTR lpCommandLine;
  250. LPSTR lpRemoveDevices;
  251. LPSTR lpAddDevices;
  252. PDEVICE_LINK p;
  253. char szWindowsDirectory[ MAX_PATH ] = {0};
  254. char chWindowsDrive;
  255. STARTUPINFO StartupInfo;
  256. PROCESS_INFORMATION ProcessInfo;
  257. NTSTATUS Status;
  258. HANDLE DirectoryHandle;
  259. PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
  260. if (!GetWindowsDirectory( szWindowsDirectory, sizeof( szWindowsDirectory ) )) {
  261. return 1;
  262. }
  263. chWindowsDrive = (char) toupper( szWindowsDirectory[ 0 ] );
  264. fVerbose = FALSE;
  265. fRemoveAllDevices = FALSE;
  266. lpCommandLine = NULL;
  267. lpRemoveDevices = NULL;
  268. lpAddDevices = NULL;
  269. while (--argc) {
  270. s = *++argv;
  271. if (*s == '-' || *s == '/') {
  272. while (c = *++s) {
  273. switch (tolower( c )) {
  274. case '?':
  275. case 'h':
  276. Usage();
  277. case 'v':
  278. fVerbose = TRUE;
  279. break;
  280. case 'r':
  281. if (c == 'R') {
  282. fRemoveAllDevices = TRUE;
  283. }
  284. else
  285. if (--argc) {
  286. lpRemoveDevices = *++argv;
  287. }
  288. else {
  289. fprintf( stderr, "DEVMAP: missing parameter to -r switch\n" );
  290. Usage();
  291. }
  292. break;
  293. case 'a':
  294. if (--argc) {
  295. lpAddDevices = *++argv;
  296. }
  297. else {
  298. fprintf( stderr, "DEVMAP: missing parameter to -r switch\n" );
  299. Usage();
  300. }
  301. break;
  302. }
  303. }
  304. }
  305. else
  306. if (lpCommandLine == NULL) {
  307. lpCommandLine = s;
  308. break;
  309. }
  310. else {
  311. Usage();
  312. }
  313. }
  314. if (lpCommandLine != NULL) {
  315. lpCommandLine = strstr( GetCommandLine(), lpCommandLine );
  316. }
  317. if (lpCommandLine == NULL) {
  318. lpCommandLine = "CMD.EXE";
  319. }
  320. cch = QueryDosDevice( NULL,
  321. DeviceNames,
  322. sizeof( DeviceNames )
  323. );
  324. if (cch == 0) {
  325. fprintf( stderr, "DOSDEV: Unable to query device names - %u\n", GetLastError() );
  326. exit( 1 );
  327. }
  328. s = DeviceNames;
  329. while (*s) {
  330. cch = QueryDosDevice( s,
  331. TargetPath,
  332. sizeof( TargetPath )
  333. );
  334. if (cch == 0) {
  335. sprintf( TargetPath, "*** unable to query target path - %u ***", GetLastError() );
  336. }
  337. else {
  338. if (strlen( s ) == 2 && s[1] == ':') {
  339. p = &DriveLetters[ NumberOfDriveLetters++ ];
  340. if (chWindowsDrive == toupper( *s )) {
  341. p->ProtectedDevice = TRUE;
  342. }
  343. }
  344. else {
  345. p = &Devices[ NumberOfDevices++ ];
  346. }
  347. p->LinkName = s;
  348. p->LinkTargetLength = cch;
  349. p->LinkTarget = malloc( cch );
  350. if (!p->LinkTarget) {
  351. return 1;
  352. }
  353. memmove( p->LinkTarget, TargetPath, cch );
  354. }
  355. while (*s++)
  356. ;
  357. }
  358. qsort( DriveLetters,
  359. NumberOfDriveLetters,
  360. sizeof( DEVICE_LINK ),
  361. CompareDeviceLink
  362. );
  363. qsort( Devices,
  364. NumberOfDevices,
  365. sizeof( DEVICE_LINK ),
  366. CompareDeviceLink
  367. );
  368. if (fVerbose) {
  369. printf( "Existing Device Names\n" );
  370. for (i=0; i<NumberOfDriveLetters; i++) {
  371. p = &DriveLetters[ i ];
  372. DisplayDeviceTarget( " ", p->LinkName, p->LinkTarget, p->LinkTargetLength );
  373. printf( "\n" );
  374. }
  375. for (i=0; i<NumberOfDevices; i++) {
  376. p = &Devices[ i ];
  377. DisplayDeviceTarget( " ", p->LinkName, p->LinkTarget, p->LinkTargetLength );
  378. printf( "\n" );
  379. }
  380. }
  381. if (fRemoveAllDevices) {
  382. for (i=0; i<NumberOfDriveLetters; i++) {
  383. DriveLetters[ i ].RemoveDevice = TRUE;
  384. }
  385. for (i=0; i<NumberOfDevices; i++) {
  386. Devices[ i ].RemoveDevice = TRUE;
  387. }
  388. }
  389. while (s = lpRemoveDevices) {
  390. while (*s && *s != ' ') {
  391. s++;
  392. }
  393. c = *s;
  394. *s++ = '\0';
  395. if (p = FindDevice( lpRemoveDevices, FALSE )) {
  396. p->RemoveDevice = TRUE;
  397. }
  398. if (c) {
  399. lpRemoveDevices = s;
  400. }
  401. else {
  402. lpRemoveDevices = NULL;
  403. }
  404. }
  405. while (s = lpAddDevices) {
  406. while (*s && *s != ' ') {
  407. s++;
  408. }
  409. c = *s;
  410. *s++ = '\0';
  411. if (p = FindDevice( lpAddDevices, TRUE )) {
  412. p->RemoveDevice = FALSE;
  413. }
  414. if (c) {
  415. lpAddDevices = s;
  416. }
  417. else {
  418. lpAddDevices = NULL;
  419. }
  420. }
  421. if (fVerbose) {
  422. printf( "Launching '%s' with following Device Names\n", lpCommandLine );
  423. }
  424. memset( &StartupInfo, 0, sizeof( StartupInfo ) );
  425. StartupInfo.cb = sizeof( StartupInfo );
  426. if (!CreateProcess( NULL,
  427. lpCommandLine,
  428. NULL,
  429. NULL,
  430. TRUE,
  431. CREATE_SUSPENDED,
  432. NULL,
  433. NULL,
  434. &StartupInfo,
  435. &ProcessInfo
  436. )
  437. ) {
  438. fprintf( stderr, "DEVMAP: CreateProcess failed - %u\n", GetLastError() );
  439. return 1;
  440. }
  441. Status = NtCreateDirectoryObject( &DirectoryHandle,
  442. DIRECTORY_ALL_ACCESS,
  443. NULL
  444. );
  445. if (!NT_SUCCESS( Status )) {
  446. fprintf( stderr, "DEVMAP: NtCreateDirectoryObject failed - %x\n", Status );
  447. return 1;
  448. }
  449. ProcessDeviceMapInfo.Set.DirectoryHandle = DirectoryHandle;
  450. Status = NtSetInformationProcess( ProcessInfo.hProcess,
  451. ProcessDeviceMap,
  452. &ProcessDeviceMapInfo.Set,
  453. sizeof( ProcessDeviceMapInfo.Set )
  454. );
  455. if (!NT_SUCCESS( Status )) {
  456. fprintf( stderr, "DEVMAP: Set ProcessDeviceMap failed - %x\n", Status );
  457. exit(1);
  458. }
  459. EnableCreatePermanentPrivilege();
  460. for (i=0; i<NumberOfDriveLetters; i++) {
  461. p = &DriveLetters[ i ];
  462. if (!p->RemoveDevice || p->ProtectedDevice) {
  463. if (fVerbose) {
  464. DisplayDeviceTarget( " ", p->LinkName, p->LinkTarget, p->LinkTargetLength );
  465. if (p->RemoveDevice && p->ProtectedDevice) {
  466. printf( " (*** may not remove boot device)" );
  467. }
  468. }
  469. CreateSymbolicLink( DirectoryHandle,
  470. p->LinkName,
  471. p->LinkTarget,
  472. p->LinkTargetLength,
  473. fVerbose
  474. );
  475. if (fVerbose) {
  476. printf( "\n" );
  477. }
  478. }
  479. }
  480. for (i=0; i<NumberOfDevices; i++) {
  481. p = &Devices[ i ];
  482. if (!p->RemoveDevice || p->ProtectedDevice) {
  483. if (fVerbose) {
  484. DisplayDeviceTarget( " ", p->LinkName, p->LinkTarget, p->LinkTargetLength );
  485. }
  486. CreateSymbolicLink( DirectoryHandle,
  487. p->LinkName,
  488. p->LinkTarget,
  489. p->LinkTargetLength,
  490. fVerbose
  491. );
  492. if (fVerbose) {
  493. printf( "\n" );
  494. }
  495. }
  496. }
  497. DisableCreatePermanentPrivilege();
  498. NtClose( DirectoryHandle );
  499. ResumeThread( ProcessInfo.hThread );
  500. WaitForSingleObject( ProcessInfo.hProcess, 0xffffffff );
  501. return 0;
  502. }