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.

380 lines
9.6 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*****************************************************************************
  3. *
  4. * QOBJECT.C for Windows NT
  5. *
  6. * Description:
  7. *
  8. * Query NT Objects.
  9. *
  10. ****************************************************************************/
  11. /* include files */
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <winstaw.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <utilsub.h>
  21. #include <printfoa.h>
  22. #include "qobject.h"
  23. /*
  24. * Local variables
  25. */
  26. WCHAR objectW[MAX_FILE_LEN+1];
  27. USHORT dev_flag = FALSE;
  28. USHORT help_flag = FALSE;
  29. /*
  30. * Command line parsing strucutre
  31. */
  32. TOKMAP ptm[] =
  33. {
  34. {L" ", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_FILE_LEN, objectW},
  35. {L"/Device", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &dev_flag},
  36. {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &help_flag},
  37. {0, 0, 0, 0, 0}
  38. };
  39. /*
  40. * Local function prototypes
  41. */
  42. VOID Usage(BOOL);
  43. BOOL AreWeRunningTerminalServices(void);
  44. /*
  45. * External Procedure prototypes
  46. */
  47. void display_devices( void );
  48. /*******************************************************************************
  49. *
  50. * print
  51. * Display a message to stdout with variable arguments. Message
  52. * format string comes from the application resources.
  53. *
  54. * ENTRY:
  55. * nResourceID (input)
  56. * Resource ID of the format string to use in the message.
  57. * ... (input)
  58. * Optional additional arguments to be used with format string.
  59. *
  60. * EXIT:
  61. *
  62. ******************************************************************************/
  63. void
  64. Print( int nResourceID, ... )
  65. {
  66. char sz1[256], sz2[512];
  67. va_list args;
  68. va_start( args, nResourceID );
  69. if ( LoadStringA( NULL, nResourceID, sz1, 256 ) ) {
  70. vsprintf( sz2, sz1, args );
  71. printf( sz2 );
  72. }
  73. va_end(args);
  74. }
  75. /*******************************************************************************
  76. *
  77. * QueryLink
  78. *
  79. ******************************************************************************/
  80. void
  81. QueryLink( HANDLE DirectoryHandle, PCWSTR pName, PWSTR pLinkName, ULONG Length )
  82. {
  83. UNICODE_STRING UnicodeString;
  84. OBJECT_ATTRIBUTES Attributes;
  85. ULONG ReturnedLength;
  86. HANDLE LinkHandle;
  87. NTSTATUS Status;
  88. pLinkName[ 0 ] = UNICODE_NULL;
  89. pLinkName[ 1 ] = UNICODE_NULL;
  90. RtlInitUnicodeString( &UnicodeString, pName );
  91. InitializeObjectAttributes( &Attributes,
  92. &UnicodeString,
  93. OBJ_CASE_INSENSITIVE,
  94. DirectoryHandle,
  95. NULL
  96. );
  97. Status = NtOpenSymbolicLinkObject( &LinkHandle,
  98. SYMBOLIC_LINK_QUERY,
  99. &Attributes
  100. );
  101. if (NT_SUCCESS( Status )) {
  102. UnicodeString.Buffer = pLinkName;
  103. UnicodeString.Length = 0;
  104. UnicodeString.MaximumLength = (USHORT)(Length * sizeof( WCHAR ));
  105. ReturnedLength = 0;
  106. Status = NtQuerySymbolicLinkObject( LinkHandle,
  107. &UnicodeString,
  108. &ReturnedLength
  109. );
  110. NtClose( LinkHandle );
  111. if (NT_SUCCESS( Status )) {
  112. pLinkName[ (ReturnedLength >> 1) + 0 ] = UNICODE_NULL;
  113. pLinkName[ (ReturnedLength >> 1) + 1 ] = UNICODE_NULL;
  114. }
  115. else {
  116. pLinkName[ 0 ] = UNICODE_NULL;
  117. pLinkName[ 1 ] = UNICODE_NULL;
  118. }
  119. }
  120. }
  121. /*******************************************************************************
  122. *
  123. * QueryObject
  124. *
  125. ******************************************************************************/
  126. void
  127. QueryObject( PCWSTR lpDeviceName )
  128. {
  129. NTSTATUS Status;
  130. UNICODE_STRING UnicodeString;
  131. OBJECT_ATTRIBUTES Attributes;
  132. HANDLE DirectoryHandle;
  133. POBJECT_DIRECTORY_INFORMATION DirInfo;
  134. BOOLEAN RestartScan;
  135. UCHAR DirInfoBuffer[ 512 ];
  136. WCHAR NameBuffer[ 256 ];
  137. WCHAR LinkBuffer[ 256 ];
  138. ULONG Context = 0;
  139. ULONG ReturnedLength;
  140. WCHAR * pInfo;
  141. RtlInitUnicodeString( &UnicodeString, lpDeviceName );
  142. InitializeObjectAttributes( &Attributes,
  143. &UnicodeString,
  144. OBJ_CASE_INSENSITIVE,
  145. NULL,
  146. NULL
  147. );
  148. Status = NtOpenDirectoryObject( &DirectoryHandle,
  149. DIRECTORY_QUERY,
  150. &Attributes
  151. );
  152. // printf( "NtOpenDirectoryObject: %x\n", Status );
  153. if (!NT_SUCCESS( Status ))
  154. return;
  155. RestartScan = TRUE;
  156. DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer;
  157. while (TRUE) {
  158. Status = NtQueryDirectoryObject( DirectoryHandle,
  159. (PVOID)DirInfo,
  160. sizeof( DirInfoBuffer ),
  161. TRUE,
  162. RestartScan,
  163. &Context,
  164. &ReturnedLength
  165. );
  166. // printf( "NtQueryDirectoryObject: %x\n", Status );
  167. if (!NT_SUCCESS( Status )) {
  168. if (Status == STATUS_NO_MORE_ENTRIES)
  169. Status = STATUS_SUCCESS;
  170. break;
  171. }
  172. swprintf( NameBuffer, L"%s%s%s", lpDeviceName,
  173. (PCWSTR) (!wcscmp(lpDeviceName,L"\\") ? L"" : L"\\"),
  174. DirInfo->Name.Buffer );
  175. if ( !wcscmp( DirInfo->TypeName.Buffer, L"SymbolicLink" ) ) {
  176. QueryLink( DirectoryHandle, DirInfo->Name.Buffer, LinkBuffer, 255 );
  177. wprintf( L"%-50s ", NameBuffer );
  178. pInfo = LinkBuffer;
  179. while ( *pInfo ) {
  180. wprintf( L"%s ", pInfo );
  181. pInfo += (wcslen( pInfo ) + 1);
  182. }
  183. wprintf( L"\n" );
  184. } else {
  185. wprintf( L"%-50s %s\n", NameBuffer, DirInfo->TypeName.Buffer );
  186. QueryObject( NameBuffer );
  187. }
  188. RestartScan = FALSE;
  189. }
  190. NtClose( DirectoryHandle );
  191. }
  192. /*******************************************************************************
  193. *
  194. * Usage
  195. *
  196. ******************************************************************************/
  197. VOID
  198. Usage( BOOL bError )
  199. {
  200. if ( bError ) {
  201. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  202. ErrorPrintf(IDS_HELP_USAGE1);
  203. ErrorPrintf(IDS_HELP_USAGE2);
  204. ErrorPrintf(IDS_HELP_USAGE3);
  205. ErrorPrintf(IDS_HELP_USAGE4);
  206. ErrorPrintf(IDS_HELP_USAGE5);
  207. } else {
  208. Print(IDS_HELP_USAGE1);
  209. Print(IDS_HELP_USAGE2);
  210. Print(IDS_HELP_USAGE3);
  211. Print(IDS_HELP_USAGE4);
  212. Print(IDS_HELP_USAGE5);
  213. }
  214. }
  215. /*******************************************************************************
  216. *
  217. * main
  218. *
  219. ******************************************************************************/
  220. int __cdecl
  221. main( int argc, char *argv[] )
  222. {
  223. INT i;
  224. ULONG rc;
  225. WCHAR **argvW;
  226. //Check if we are running under Terminal Server
  227. if(!AreWeRunningTerminalServices())
  228. {
  229. ErrorPrintf(IDS_ERROR_NOT_TS);
  230. return(FAILURE);
  231. }
  232. /*
  233. * No popups
  234. */
  235. SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  236. /*
  237. * Massage the new command line to look like an argv[] type
  238. * because ParseCommandLine() depends on this format
  239. */
  240. argvW = (WCHAR **)malloc( sizeof(WCHAR *) * (argc+1) );
  241. if(argvW == NULL) {
  242. ErrorPrintf(IDS_ERROR_MALLOC);
  243. return STATUS_NO_MEMORY;
  244. }
  245. for( i=0; i < argc; i++ ) {
  246. // Convert to Ansi
  247. OEM2ANSIA(argv[i], (USHORT)strlen(argv[i]));
  248. argvW[i] = (WCHAR *)malloc( (strlen(argv[i]) + 1) * sizeof(WCHAR) );
  249. wsprintf( argvW[i], L"%S", argv[i] );
  250. }
  251. argvW[argc] = NULL;
  252. /*
  253. * parse the cmd line without parsing the program name (argc-1, argv+1)
  254. */
  255. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  256. /*
  257. * Check for error from ParseCommandLine
  258. */
  259. if ( help_flag || (rc && rc != PARSE_FLAG_NO_PARMS) ) {
  260. if ( !help_flag ) {
  261. Usage(TRUE);
  262. return rc;
  263. } else {
  264. Usage(FALSE);
  265. return ERROR_SUCCESS;
  266. }
  267. }
  268. /*
  269. * Dos devices only
  270. */
  271. if ( dev_flag ) {
  272. display_devices();
  273. }
  274. else {
  275. if ( ptm[0].tmFlag & TMFLAG_PRESENT ) {
  276. QueryObject( objectW );
  277. } else {
  278. QueryObject( L"\\" );
  279. }
  280. }
  281. return( 0 );
  282. }
  283. /*******************************************************************************
  284. *
  285. * AreWeRunningTerminalServices
  286. *
  287. * Check if we are running terminal server
  288. *
  289. * ENTRY:
  290. *
  291. * EXIT: BOOL: True if we are running Terminal Services False if we
  292. * are not running Terminal Services
  293. *
  294. *
  295. ******************************************************************************/
  296. BOOL AreWeRunningTerminalServices(void)
  297. {
  298. OSVERSIONINFOEX osVersionInfo;
  299. DWORDLONG dwlConditionMask = 0;
  300. ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  301. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  302. osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;
  303. VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
  304. return VerifyVersionInfo(
  305. &osVersionInfo,
  306. VER_SUITENAME,
  307. dwlConditionMask
  308. );
  309. }