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.

422 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. object.c
  5. Abstract:
  6. Resource DLL for disks.
  7. Author:
  8. Rod Gamache (rodga) 18-Dec-1995
  9. Revision History:
  10. --*/
  11. #include "nt.h"
  12. #include "ntrtl.h"
  13. #include "nturtl.h"
  14. #include "windows.h"
  15. #include "windef.h"
  16. #include "stdio.h"
  17. #include "stdlib.h"
  18. #include "disksp.h"
  19. #define ATTR_DIR 0x00000001
  20. #define ATTR_DEVICE 0x00000002
  21. #define ATTR_FILE 0x00000004
  22. #define ATTR_SYMLINK 0x00000008
  23. #define DIRECTORYTYPE L"Directory"
  24. #define DEVICETYPE L"Device"
  25. #define FILETYPE L"File"
  26. #define SYMLINKTYPE L"SymbolicLink"
  27. /* Converts the type-name into an attribute value */
  28. LONG CalcAttributes(
  29. PUNICODE_STRING Type
  30. )
  31. {
  32. UNICODE_STRING TypeName;
  33. RtlInitUnicodeString(&TypeName, DIRECTORYTYPE);
  34. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  35. return ATTR_DIR;
  36. }
  37. RtlInitUnicodeString(&TypeName, DEVICETYPE);
  38. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  39. return ATTR_DEVICE;
  40. }
  41. RtlInitUnicodeString(&TypeName, FILETYPE);
  42. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  43. return ATTR_FILE;
  44. }
  45. RtlInitUnicodeString(&TypeName, SYMLINKTYPE);
  46. if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
  47. return ATTR_SYMLINK;
  48. }
  49. return(0);
  50. } // CalcAttributes
  51. /*--------------------------------------------------------------------------*/
  52. /* */
  53. /* StripObjectSpec() - */
  54. /* */
  55. /*--------------------------------------------------------------------------*/
  56. /* Remove the filespec portion from a path (including the backslash). */
  57. VOID StripObjectSpec(LPSTR lpszPath)
  58. {
  59. LPSTR p;
  60. #ifdef DBCS
  61. p = lpszPath + lstrlen(lpszPath);
  62. while ((*p != '\\') && (p != lpszPath))
  63. p = AnsiPrev(lpszPath, p);
  64. #else
  65. p = lpszPath + lstrlen(lpszPath);
  66. while ((*p != '\\') && (p != lpszPath))
  67. p--;
  68. #endif
  69. /* Don't strip backslash from root directory entry. */
  70. if ((p == lpszPath) && (*p == '\\')) {
  71. p++;
  72. }
  73. *p = '\000';
  74. } // StripObjectSpec
  75. /*--------------------------------------------------------------------------*/
  76. /* */
  77. /* StripObjectPath() - */
  78. /* */
  79. /*--------------------------------------------------------------------------*/
  80. /* Extract only the filespec portion from a path. */
  81. VOID StripObjectPath(LPSTR lpszPath)
  82. {
  83. LPSTR p;
  84. p = lpszPath + lstrlen(lpszPath);
  85. #ifdef DBCS
  86. while ((*p != '\\') && (p != lpszPath))
  87. p = AnsiPrev(lpszPath, p);
  88. #else
  89. while ((*p != '\\') && (p != lpszPath))
  90. p--;
  91. #endif
  92. if (*p == '\\')
  93. p++;
  94. if (p != lpszPath)
  95. lstrcpy(lpszPath, p);
  96. } // StripObjectPath
  97. VOID
  98. GetSymbolicLink(
  99. IN PCHAR RootName,
  100. IN OUT PCHAR ObjectName, // Assume this points at a MAX_PATH len buffer
  101. IN PDISK_INFO DiskInfo
  102. )
  103. {
  104. NTSTATUS Status;
  105. OBJECT_ATTRIBUTES Object_Attributes;
  106. HANDLE LinkHandle;
  107. STRING String;
  108. WCHAR UnicodeBuffer[MAX_PATH];
  109. CHAR Buffer[2*MAX_PATH];
  110. UNICODE_STRING UnicodeString;
  111. strcpy( Buffer, RootName );
  112. strcat( Buffer, ObjectName );
  113. RtlInitString(&String, Buffer);
  114. Status = RtlAnsiStringToUnicodeString( &UnicodeString,
  115. &String,
  116. TRUE );
  117. ASSERT( NT_SUCCESS( Status ) );
  118. InitializeObjectAttributes(&Object_Attributes,
  119. &UnicodeString,
  120. OBJ_CASE_INSENSITIVE,
  121. NULL,
  122. NULL
  123. );
  124. // Open the given symbolic link object
  125. Status = NtOpenSymbolicLinkObject(&LinkHandle,
  126. GENERIC_ALL,
  127. &Object_Attributes);
  128. RtlFreeUnicodeString(&UnicodeString);
  129. if (!NT_SUCCESS(Status)) {
  130. printf( "Open symbolic link failed, status = %u.\n",
  131. Status);
  132. return;
  133. }
  134. // Set up our String variable to point at the object name buffer
  135. String.Length = 0;
  136. String.MaximumLength = (USHORT)(MAX_PATH);
  137. String.Buffer = ObjectName;
  138. // Go get the target of the symbolic link
  139. UnicodeString.Buffer = UnicodeBuffer;
  140. UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
  141. Status = NtQuerySymbolicLinkObject(LinkHandle, &UnicodeString, NULL);
  142. NtClose(LinkHandle);
  143. if (!NT_SUCCESS(Status)) {
  144. printf("Query symbolic link failed, status = %u.\n",
  145. Status);
  146. return;
  147. }
  148. // Copy the symbolic target into return buffer
  149. Status = RtlUnicodeStringToAnsiString(&String, &UnicodeString, FALSE);
  150. ASSERT(NT_SUCCESS(Status));
  151. // Add NULL terminator
  152. String.Buffer[String.Length] = 0;
  153. return;
  154. }
  155. /* Open the object given only its name.
  156. * First find the object type by enumerating the directory entries.
  157. * Then call the type-specific open routine to get a handle
  158. */
  159. HANDLE
  160. OpenObject(
  161. LPSTR lpstrDirectory,
  162. LPSTR lpstrObject,
  163. PDISK_INFO DiskInfo
  164. )
  165. {
  166. #define BUFFER_SIZE 1024
  167. NTSTATUS Status;
  168. HANDLE DirectoryHandle;
  169. ULONG Context = 0;
  170. ULONG ReturnedLength;
  171. CHAR Buffer[BUFFER_SIZE];
  172. CHAR StringBuffer[BUFFER_SIZE];
  173. CHAR CompareBuffer[MAX_PATH];
  174. CHAR ReturnBuffer[MAX_PATH];
  175. ANSI_STRING AnsiString;
  176. POBJECT_DIRECTORY_INFORMATION DirInfo;
  177. WCHAR ObjectNameBuf[MAX_PATH];
  178. UNICODE_STRING ObjectName;
  179. WCHAR ObjectTypeBuf[MAX_PATH];
  180. UNICODE_STRING ObjectType;
  181. HANDLE ObjectHandle;
  182. OBJECT_ATTRIBUTES Attributes;
  183. UNICODE_STRING DirectoryName;
  184. IO_STATUS_BLOCK IOStatusBlock;
  185. BOOL NotFound;
  186. //DbgPrint("Open object: raw full name = <%s>\n", lpstrObject);
  187. #if 0
  188. // Remove drive letter
  189. while ((*lpstrObject != 0) && (*lpstrObject != '\\')) {
  190. lpstrObject++;
  191. }
  192. #endif
  193. //DbgPrint("Open object: full name = <%s%s>\n", lpstrDirectory, lpstrObject);
  194. // Initialize the object type buffer
  195. ObjectType.Buffer = ObjectTypeBuf;
  196. ObjectType.MaximumLength = sizeof(ObjectTypeBuf);
  197. // Initialize the object name string
  198. //strcpy(Buffer, lpstrObject);
  199. //StripObjectPath(Buffer);
  200. RtlInitAnsiString(&AnsiString, lpstrObject);
  201. ObjectName.Buffer = ObjectNameBuf;
  202. ObjectName.MaximumLength = sizeof(ObjectNameBuf);
  203. Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, FALSE);
  204. ASSERT(NT_SUCCESS(Status));
  205. //DbgPrint("Open object: name only = <%wZ>\n", &ObjectName);
  206. // Form buffer to compare Object entries against.
  207. strcpy(CompareBuffer, lpstrObject );
  208. //StripObjectSpec( CompareBuffer );
  209. //
  210. // Open the directory for list directory access
  211. //
  212. strcpy(StringBuffer, lpstrDirectory);
  213. //StripObjectSpec(Buffer);
  214. RtlInitAnsiString(&AnsiString, StringBuffer);
  215. Status = RtlAnsiStringToUnicodeString( &DirectoryName, &AnsiString, TRUE);
  216. ASSERT(NT_SUCCESS(Status));
  217. InitializeObjectAttributes( &Attributes,
  218. &DirectoryName,
  219. OBJ_CASE_INSENSITIVE,
  220. NULL,
  221. NULL );
  222. //DbgPrint("Open object: dir only = <%wZ>\n", &DirectoryName);
  223. if (!NT_SUCCESS( Status = NtOpenDirectoryObject( &DirectoryHandle,
  224. STANDARD_RIGHTS_READ |
  225. DIRECTORY_QUERY |
  226. DIRECTORY_TRAVERSE,
  227. &Attributes ) )) {
  228. if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
  229. DbgPrint( "%wZ is not a valid Object Directory Object name\n",
  230. &DirectoryName );
  231. } else {
  232. DbgPrint("OpenObject: failed to open directory, status = 0x%lx\n\r", Status);
  233. }
  234. RtlFreeUnicodeString(&DirectoryName);
  235. printf("Unable to open object.\n");
  236. return NULL;
  237. }
  238. RtlFreeUnicodeString(&DirectoryName);
  239. //
  240. // Query the entire directory in one sweep
  241. //
  242. NotFound = TRUE;
  243. for (Status = NtQueryDirectoryObject( DirectoryHandle,
  244. Buffer,
  245. sizeof(Buffer),
  246. // LATER FALSE,
  247. TRUE, // one entry at a time for now
  248. TRUE,
  249. &Context,
  250. &ReturnedLength );
  251. NotFound;
  252. Status = NtQueryDirectoryObject( DirectoryHandle,
  253. Buffer,
  254. sizeof(Buffer),
  255. // LATER FALSE,
  256. TRUE, // one entry at a time for now
  257. FALSE,
  258. &Context,
  259. &ReturnedLength ) ) {
  260. //
  261. // Check the status of the operation.
  262. //
  263. if (!NT_SUCCESS( Status )) {
  264. if (Status != STATUS_NO_MORE_ENTRIES) {
  265. printf("Failed to query directory object, status = %%1!u!.",
  266. Status);
  267. }
  268. break;
  269. }
  270. //
  271. // For every record in the buffer get the symbolic link and
  272. // compare the name of the symbolic link with the one we're
  273. // looking for.
  274. //
  275. //
  276. // Point to the first record in the buffer, we are guaranteed to have
  277. // one otherwise Status would have been No More Files
  278. //
  279. DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
  280. RtlCopyString( (PSTRING)&ObjectType, (PSTRING)&DirInfo->TypeName);
  281. AnsiString.MaximumLength = BUFFER_SIZE;
  282. while ( DirInfo->Name.Length != 0 ) {
  283. //DbgPrint("Found object <%wZ>\n", &(DirInfo->Name));
  284. RtlCopyString( (PSTRING)&ObjectType, (PSTRING)&DirInfo->TypeName);
  285. if ( CalcAttributes(&ObjectType) == ATTR_SYMLINK ) {
  286. RtlUnicodeStringToAnsiString( &AnsiString,
  287. &(DirInfo->Name),
  288. FALSE );
  289. strcpy( ReturnBuffer, AnsiString.Buffer );
  290. GetSymbolicLink( "\\DosDevices\\", ReturnBuffer, DiskInfo);
  291. if ( strncmp( ReturnBuffer, CompareBuffer, strlen(CompareBuffer) ) == 0 &&
  292. AnsiString.Buffer[strlen(AnsiString.Buffer)-1] == ':' ) {
  293. NotFound = FALSE;
  294. break;
  295. }
  296. }
  297. DirInfo++;
  298. }
  299. } // for
  300. NtClose(DirectoryHandle);
  301. if ( NotFound ) {
  302. SetLastError(ERROR_FILE_NOT_FOUND);
  303. return(NULL);
  304. }
  305. // We now have the type of the object in ObjectType
  306. // We still have the full object name in lpstrObject
  307. // Use the appropriate open routine to get a handle
  308. sprintf( Buffer, "\\\\.\\%s", AnsiString.Buffer );
  309. ObjectHandle = CreateFile( Buffer,
  310. GENERIC_READ | GENERIC_WRITE,
  311. FILE_SHARE_WRITE | FILE_SHARE_READ,
  312. NULL,
  313. OPEN_EXISTING,
  314. 0,
  315. NULL );
  316. return(ObjectHandle);
  317. } // OpenObject