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.

679 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. namespac.c
  5. Abstract:
  6. This file contains all of the namespace handling functions
  7. Author:
  8. Based on code by Mike Tsang (MikeTs)
  9. Stephane Plante (Splante)
  10. Environment:
  11. User mode only
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. PNSOBJ RootNameSpaceObject;
  16. PNSOBJ CurrentScopeNameSpaceObject;
  17. PNSOBJ CurrentOwnerNameSpaceObject;
  18. NTSTATUS
  19. LOCAL
  20. CreateNameSpaceObject(
  21. PUCHAR ObjectName,
  22. PNSOBJ ObjectScope,
  23. PNSOBJ ObjectOwner,
  24. PNSOBJ *Object,
  25. ULONG Flags
  26. )
  27. /*++
  28. Routine Description:
  29. This routine creates a name space object under the current scope
  30. Arguments:
  31. ObjectName - Name Path String
  32. ObjectScope - Scope to start the search from (NULL == Root)
  33. ObjectOwner - The object which owns this one
  34. Object - Where to store the point to the object that we just created
  35. Flags - Options
  36. Return Value:
  37. NTSTATUS
  38. --*/
  39. {
  40. NTSTATUS status = STATUS_SUCCESS;
  41. PNSOBJ localObject;
  42. ENTER( (
  43. 1,
  44. "CreateNameSpaceObject(%s,Scope=%s,Owner=%p,Object=%p,"
  45. "Flag=%08lx)\n",
  46. ObjectName,
  47. (ObjectScope ? GetObjectPath( ObjectScope ) : "ROOT"),
  48. ObjectOwner,
  49. Object,
  50. Flags
  51. ) );
  52. if (ObjectScope == NULL) {
  53. ObjectScope = RootNameSpaceObject;
  54. }
  55. status = GetNameSpaceObject(
  56. ObjectName,
  57. ObjectScope,
  58. &localObject,
  59. NSF_LOCAL_SCOPE
  60. );
  61. if (NT_SUCCESS(status)) {
  62. if (!(Flags & NSF_EXIST_OK)) {
  63. status = STATUS_OBJECT_NAME_COLLISION;
  64. }
  65. } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  66. status = STATUS_SUCCESS;
  67. //
  68. // Are we creating root?
  69. //
  70. if (strcmp(ObjectName,"\\") == 0) {
  71. ASSERT( RootNameSpaceObject == NULL );
  72. ASSERT( ObjectOwner == NULL );
  73. localObject = MEMALLOC( sizeof(NSOBJ) );
  74. if (localObject == NULL) {
  75. return STATUS_INSUFFICIENT_RESOURCES;
  76. } else {
  77. memset( localObject, 0, sizeof(NSOBJ) );
  78. localObject->Signature = SIG_NSOBJ;
  79. localObject->NameSeg = NAMESEG_ROOT;
  80. RootNameSpaceObject = localObject;
  81. }
  82. } else {
  83. PUCHAR nameEnd;
  84. PNSOBJ objectParent;
  85. nameEnd = strrchr(ObjectName, '.');
  86. if (nameEnd != NULL) {
  87. *nameEnd = '\0';
  88. nameEnd++;
  89. status = GetNameSpaceObject(
  90. ObjectName,
  91. ObjectScope,
  92. &objectParent,
  93. NSF_LOCAL_SCOPE
  94. );
  95. } else if (*ObjectName == '\\') {
  96. nameEnd = &ObjectName[1];
  97. ASSERT( RootNameSpaceObject != NULL );
  98. objectParent = RootNameSpaceObject;
  99. } else if (*ObjectName == '^') {
  100. nameEnd = ObjectName;
  101. objectParent = ObjectScope;
  102. while ( (*nameEnd == '^') && (objectParent != NULL)) {
  103. objectParent = objectParent->ParentObject;
  104. nameEnd++;
  105. }
  106. } else {
  107. ASSERT( ObjectScope );
  108. nameEnd = ObjectName;
  109. objectParent = ObjectScope;
  110. }
  111. if (status == STATUS_SUCCESS) {
  112. ULONG length = strlen(nameEnd);
  113. localObject = MEMALLOC( sizeof(NSOBJ) );
  114. if (localObject == NULL) {
  115. status = STATUS_INSUFFICIENT_RESOURCES;
  116. } else if ( (*nameEnd != '\0') && (length > sizeof(NAMESEG))) {
  117. status = STATUS_OBJECT_NAME_INVALID;
  118. MEMFREE( localObject );
  119. } else {
  120. memset( localObject, 0, sizeof(NSOBJ) );
  121. localObject->Signature = SIG_NSOBJ;
  122. localObject->NameSeg = NAMESEG_BLANK;
  123. memcpy( &(localObject->NameSeg), nameEnd, length );
  124. localObject->Owner = ObjectOwner;
  125. localObject->ParentObject = objectParent;
  126. ListInsertTail(
  127. &(localObject->List),
  128. (PPLIST) &(objectParent->FirstChild)
  129. );
  130. }
  131. }
  132. }
  133. }
  134. if (NT_SUCCESS(status) && Object != NULL) {
  135. *Object = localObject;
  136. }
  137. EXIT( (
  138. 1,
  139. "CreateNameSpaceObject=%08lx (*Object=%p)\n",
  140. status,
  141. localObject
  142. ) );
  143. return status;
  144. }
  145. NTSTATUS
  146. LOCAL
  147. CreateObject(
  148. PUCHAR ObjectName,
  149. UCHAR ObjectType,
  150. PNSOBJ *Object
  151. )
  152. /*++
  153. Routine Description:
  154. Creates a NameSpace Object for the term
  155. Arguments:
  156. ObjectName - The name object object
  157. ObjectType - The type of object to create
  158. Object - Where to store a pointer to the created object
  159. Return Value:
  160. NTSTATUS
  161. --*/
  162. {
  163. NTSTATUS status = STATUS_SUCCESS;
  164. PNSOBJ localObject;
  165. ENTER( (
  166. 1,
  167. "CreateObject(%s,Type=%02x,Object=%p)\n",
  168. ObjectName,
  169. ObjectType,
  170. Object
  171. ) );
  172. status = CreateNameSpaceObject(
  173. ObjectName,
  174. CurrentScopeNameSpaceObject,
  175. CurrentOwnerNameSpaceObject,
  176. &localObject,
  177. NSF_EXIST_ERR
  178. );
  179. if (NT_SUCCESS(status)) {
  180. switch (ObjectType) {
  181. case NSTYPE_UNKNOWN:
  182. break;
  183. case NSTYPE_FIELDUNIT:
  184. localObject->ObjectData.DataType = OBJTYPE_FIELDUNIT;
  185. break;
  186. case NSTYPE_DEVICE:
  187. localObject->ObjectData.DataType = OBJTYPE_DEVICE;
  188. break;
  189. case NSTYPE_EVENT:
  190. localObject->ObjectData.DataType = OBJTYPE_EVENT;
  191. break;
  192. case NSTYPE_METHOD:
  193. localObject->ObjectData.DataType = OBJTYPE_METHOD;
  194. break;
  195. case NSTYPE_MUTEX:
  196. localObject->ObjectData.DataType = OBJTYPE_MUTEX;
  197. break;
  198. case NSTYPE_OPREGION:
  199. localObject->ObjectData.DataType = OBJTYPE_OPREGION;
  200. break;
  201. case NSTYPE_POWERRES:
  202. localObject->ObjectData.DataType = OBJTYPE_POWERRES;
  203. break;
  204. case NSTYPE_PROCESSOR:
  205. localObject->ObjectData.DataType = OBJTYPE_PROCESSOR;
  206. break;
  207. case NSTYPE_THERMALZONE:
  208. localObject->ObjectData.DataType = OBJTYPE_THERMALZONE;
  209. break;
  210. case NSTYPE_OBJALIAS:
  211. localObject->ObjectData.DataType = OBJTYPE_OBJALIAS;
  212. break;
  213. case NSTYPE_BUFFFIELD:
  214. localObject->ObjectData.DataType = OBJTYPE_BUFFFIELD;
  215. break;
  216. default:
  217. status = STATUS_OBJECT_TYPE_MISMATCH;
  218. }
  219. if (Object != NULL) {
  220. *Object = localObject;
  221. }
  222. }
  223. EXIT( (
  224. 1,
  225. "CreateObject=%08lx (*Object=%p)\n",
  226. status,
  227. localObject
  228. ) );
  229. return status;
  230. } //CreateObject
  231. NTSTATUS
  232. LOCAL
  233. GetNameSpaceObject(
  234. PUCHAR ObjectPath,
  235. PNSOBJ ScopeObject,
  236. PNSOBJ *NameObject,
  237. ULONG Flags
  238. )
  239. /*++
  240. Routine Description:
  241. This routine searches the namespace until it finds a matching object
  242. Arguments:
  243. ObjectPath - String with the Name to search for
  244. ScopeObject - Scope to start search at (NULL == ROOT)
  245. NameObject - Where to store the object, if found
  246. Flags - Options
  247. Return Value:
  248. NTSTATUS
  249. --*/
  250. {
  251. NTSTATUS status = STATUS_SUCCESS;
  252. PUCHAR subPath;
  253. ENTER( (
  254. 1,
  255. "GetNameSpaceObject(%s,Scope=%s,Object=%p,Flags=%08lx\n",
  256. ObjectPath,
  257. (ScopeObject ? GetObjectPath( ScopeObject ) : "ROOT"),
  258. NameObject,
  259. Flags
  260. ) );
  261. if (ScopeObject == NULL) {
  262. ScopeObject = RootNameSpaceObject;
  263. }
  264. if (*ObjectPath == '\\') {
  265. subPath = &ObjectPath[1];
  266. ScopeObject = RootNameSpaceObject;
  267. } else {
  268. subPath = ObjectPath;
  269. while ( (*subPath == '^') && (ScopeObject != NULL)) {
  270. subPath++;
  271. ScopeObject = ScopeObject->ParentObject;
  272. }
  273. }
  274. *NameObject = ScopeObject;
  275. if (ScopeObject == NULL) {
  276. status = STATUS_OBJECT_NAME_NOT_FOUND;
  277. } else if (*subPath != '\0') {
  278. BOOL searchUp;
  279. PNSOBJ tempObject;
  280. searchUp = !(Flags & NSF_LOCAL_SCOPE) &&
  281. (ObjectPath[0] == '\\') &&
  282. (ObjectPath[0] == '^') &&
  283. (strlen(ObjectPath) <= sizeof(NAMESEG));
  284. while (1) {
  285. do {
  286. tempObject = ScopeObject->FirstChild;
  287. if (tempObject == NULL) {
  288. status = STATUS_OBJECT_NAME_NOT_FOUND;
  289. } else {
  290. BOOL found;
  291. PUCHAR bufferEnd;
  292. ULONG length;
  293. NAMESEG nameSeg;
  294. bufferEnd = strchr( subPath, '.' );
  295. if (bufferEnd != NULL) {
  296. length = (ULONG)(bufferEnd - subPath);
  297. } else {
  298. length = strlen(subPath);
  299. }
  300. if (length > sizeof(NAMESEG)) {
  301. status = STATUS_OBJECT_NAME_INVALID;
  302. found = FALSE;
  303. } else {
  304. nameSeg = NAMESEG_BLANK;
  305. memcpy( &nameSeg, subPath, length );
  306. //
  307. // search all sibling fors a matching nameSeg
  308. //
  309. found = FALSE;
  310. do {
  311. if (tempObject->NameSeg == nameSeg) {
  312. ScopeObject = tempObject;
  313. found = TRUE;
  314. break;
  315. }
  316. tempObject = (PNSOBJ) tempObject->List.ListNext;
  317. } while (tempObject != tempObject->ParentObject->FirstChild );
  318. }
  319. if (status == STATUS_SUCCESS) {
  320. if (!found) {
  321. status = STATUS_OBJECT_NAME_NOT_FOUND;
  322. } else {
  323. subPath += length;
  324. if (*subPath == '.') {
  325. subPath++;
  326. } else if (*subPath == '\0') {
  327. *NameObject = ScopeObject;
  328. break;
  329. }
  330. }
  331. }
  332. }
  333. } while ( status == STATUS_SUCCESS );
  334. if (status == STATUS_OBJECT_NAME_NOT_FOUND && searchUp &&
  335. ScopeObject != NULL && ScopeObject->ParentObject != NULL) {
  336. ScopeObject = ScopeObject->ParentObject;
  337. status = STATUS_SUCCESS;
  338. } else {
  339. break;
  340. }
  341. }
  342. }
  343. if (status != STATUS_SUCCESS) {
  344. *NameObject = NULL;
  345. }
  346. EXIT( (
  347. 1,
  348. "GetNameSpaceObject=%08lx (*Object=%p)\n",
  349. status,
  350. *NameObject
  351. ) );
  352. return status;
  353. }
  354. PUCHAR
  355. LOCAL
  356. GetObjectPath(
  357. PNSOBJ NameObject
  358. )
  359. /*++
  360. Routine Description:
  361. This routine takes a NameSpace Object and returns a string to represent
  362. its path
  363. Arguments:
  364. NameObject - The object whose path we want
  365. Return Value:
  366. Pointer to the string which represents the path
  367. --*/
  368. {
  369. static UCHAR namePath[MAX_NAME_LEN + 1] = {0};
  370. ULONG i;
  371. ENTER( (4, "GetObjectPath(Object=%p)\n", NameObject ) );
  372. if (NameObject != NULL) {
  373. if (NameObject->ParentObject == NULL) {
  374. strcpy(namePath, "\\");
  375. } else {
  376. GetObjectPath(NameObject->ParentObject);
  377. if (NameObject->ParentObject->ParentObject != NULL) {
  378. strcat(namePath, ".");
  379. }
  380. strncat(namePath, (PUCHAR)&NameObject->NameSeg, sizeof(NAMESEG));
  381. }
  382. for (i = strlen(namePath) - 1; i >= 0; --i) {
  383. if (namePath[i] == '_') {
  384. namePath[i] = '\0';
  385. } else {
  386. break;
  387. }
  388. }
  389. } else {
  390. namePath[0] = '\0';
  391. }
  392. EXIT( (4, "GetObjectPath=%s\n", namePath ) );
  393. return namePath;
  394. }
  395. PUCHAR
  396. LOCAL
  397. GetObjectTypeName(
  398. ULONG ObjectType
  399. )
  400. /*++
  401. Routine Description:
  402. Returns a string which corresponds to the type object the object
  403. Arugment:
  404. ObjectType - The type that we wish to know about
  405. Return Value:
  406. Globally Available String
  407. --*/
  408. {
  409. PUCHAR type = NULL;
  410. ULONG i;
  411. static struct {
  412. ULONG ObjectType;
  413. PUCHAR ObjectTypeName;
  414. } ObjectTypeTable[] =
  415. {
  416. OBJTYPE_UNKNOWN, "Unknown",
  417. OBJTYPE_INTDATA, "Integer",
  418. OBJTYPE_STRDATA, "String",
  419. OBJTYPE_BUFFDATA, "Buffer",
  420. OBJTYPE_PKGDATA, "Package",
  421. OBJTYPE_FIELDUNIT, "FieldUnit",
  422. OBJTYPE_DEVICE, "Device",
  423. OBJTYPE_EVENT, "Event",
  424. OBJTYPE_METHOD, "Method",
  425. OBJTYPE_MUTEX, "Mutex",
  426. OBJTYPE_OPREGION, "OpRegion",
  427. OBJTYPE_POWERRES, "PowerResource",
  428. OBJTYPE_PROCESSOR, "Processor",
  429. OBJTYPE_THERMALZONE,"ThermalZone",
  430. OBJTYPE_BUFFFIELD, "BuffField",
  431. OBJTYPE_DDBHANDLE, "DDBHandle",
  432. OBJTYPE_DEBUG, "Debug",
  433. OBJTYPE_OBJALIAS, "ObjAlias",
  434. OBJTYPE_DATAALIAS, "DataAlias",
  435. OBJTYPE_BANKFIELD, "BankField",
  436. OBJTYPE_FIELD, "Field",
  437. OBJTYPE_INDEXFIELD, "IndexField",
  438. OBJTYPE_DATA, "Data",
  439. OBJTYPE_DATAFIELD, "DataField",
  440. OBJTYPE_DATAOBJ, "DataObject",
  441. OBJTYPE_PNP_RES, "PNPResource",
  442. OBJTYPE_RES_FIELD, "ResField",
  443. 0, NULL
  444. };
  445. ENTER( (4, "GetObjectTypeName(Type=%02x)\n", ObjectType ) );
  446. for (i = 0; ObjectTypeTable[i].ObjectTypeName != NULL; i++) {
  447. if (ObjectType == ObjectTypeTable[i].ObjectType) {
  448. type = ObjectTypeTable[i].ObjectTypeName;
  449. break;
  450. }
  451. }
  452. EXIT( (4, "GetObjectTypeName=%s\n", type ? type : "NULL" ) );
  453. return type;
  454. }