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.

256 lines
5.5 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Regclass.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 Registry
  7. APIs to open the classes root key for a specified user.
  8. - RegOpenUserClassesRoot
  9. Author:
  10. Adam Edwards (adamed) 15-Apr-1998
  11. Notes:
  12. This API is local only.
  13. See the notes in server\regkey.c.
  14. --*/
  15. #include <rpc.h>
  16. #include "regrpc.h"
  17. #include "client.h"
  18. #include <malloc.h>
  19. #define REG_USER_CLASSES_PREFIX L"\\Registry\\User\\"
  20. #define REG_USER_CLASSES_SUFFIX L"_Classes"
  21. BOOL InitializeClassesEnumTable();
  22. BOOL InitializeClassesNameSpace();
  23. BOOL CleanupClassesEnumTable(DWORD dwCriteria);
  24. BOOL CleanupClassesNameSpace();
  25. #if defined(LEAK_TRACK)
  26. NTSTATUS TrackObject(HKEY hKey);
  27. #endif // defined(LEAK_TRACK)
  28. extern BOOL gbCombinedClasses;
  29. LONG
  30. APIENTRY
  31. RegOpenUserClassesRoot(
  32. HANDLE hToken,
  33. DWORD dwOptions,
  34. REGSAM samDesired,
  35. PHKEY phkResult
  36. )
  37. /*++
  38. Routine Description:
  39. Win32 Unicode RPC wrapper for opening the classes root key
  40. for the use specified by the hToken parameter.
  41. Arguments:
  42. hToken - token for user whose classes root is to be opened. If
  43. this parameter is NULL, we return ERROR_INVALID_PARAMETER
  44. phkResult - Returns an open handle to the newly opened key.
  45. Return Value:
  46. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  47. Notes:
  48. --*/
  49. {
  50. NTSTATUS Status;
  51. UNICODE_STRING UsersHive;
  52. BYTE achBuffer[100];
  53. PTOKEN_USER pTokenInfo = (PTOKEN_USER) &achBuffer;
  54. DWORD dwBytesRequired;
  55. LONG Error;
  56. //
  57. // Caller must pass pointer to the variable where the opened handle
  58. // will be returned
  59. //
  60. if( phkResult == NULL ) {
  61. return ERROR_INVALID_PARAMETER;
  62. }
  63. if (NULL == hToken) {
  64. return ERROR_INVALID_PARAMETER;
  65. }
  66. if (dwOptions != REG_OPTION_RESERVED) {
  67. return ERROR_INVALID_PARAMETER;
  68. }
  69. if (!gbCombinedClasses) {
  70. return ERROR_FILE_NOT_FOUND;
  71. }
  72. //
  73. // open up the token to get the sid
  74. //
  75. if (!GetTokenInformation(
  76. hToken, // Handle
  77. TokenUser, // TokenInformationClass
  78. pTokenInfo, // TokenInformation
  79. sizeof(achBuffer), // TokenInformationLength
  80. &dwBytesRequired // ReturnLength
  81. )) {
  82. Error = GetLastError();
  83. //
  84. // Try again if the buffer was too small
  85. //
  86. if (ERROR_INSUFFICIENT_BUFFER != Error) {
  87. return Error ;
  88. }
  89. //
  90. // Allocate space for the user info
  91. //
  92. pTokenInfo = (PTOKEN_USER) alloca(dwBytesRequired);
  93. if (!pTokenInfo) {
  94. return ERROR_NOT_ENOUGH_MEMORY;
  95. }
  96. //
  97. // Read in the UserInfo
  98. //
  99. if (!GetTokenInformation(
  100. hToken, // Handle
  101. TokenUser, // TokenInformationClass
  102. pTokenInfo, // TokenInformation
  103. dwBytesRequired, // TokenInformationLength
  104. &dwBytesRequired // ReturnLength
  105. )) {
  106. return GetLastError();
  107. }
  108. }
  109. //
  110. // Change sid to a string
  111. //
  112. Status = RtlConvertSidToUnicodeString(
  113. &UsersHive,
  114. pTokenInfo->User.Sid,
  115. TRUE); // allocate the string
  116. if (NT_SUCCESS(Status)) {
  117. UNICODE_STRING UserClassesString;
  118. UserClassesString.MaximumLength = UsersHive.Length +
  119. sizeof(REG_USER_CLASSES_PREFIX) +
  120. sizeof(REG_USER_CLASSES_SUFFIX);
  121. UserClassesString.Buffer = (WCHAR*) alloca(UserClassesString.MaximumLength);
  122. if (UserClassesString.Buffer) {
  123. UNICODE_STRING UserPrefix;
  124. //
  125. // construct the name
  126. //
  127. RtlInitUnicodeString(&UserPrefix, REG_USER_CLASSES_PREFIX);
  128. RtlCopyUnicodeString(&UserClassesString, &UserPrefix);
  129. Status = RtlAppendUnicodeStringToString(&UserClassesString, &UsersHive);
  130. if (NT_SUCCESS(Status)) {
  131. Status = RtlAppendUnicodeToString(&UserClassesString,
  132. REG_USER_CLASSES_SUFFIX);
  133. }
  134. if (NT_SUCCESS(Status)) {
  135. OBJECT_ATTRIBUTES Obja;
  136. // open this key
  137. InitializeObjectAttributes(
  138. &Obja,
  139. &UserClassesString,
  140. OBJ_CASE_INSENSITIVE,
  141. NULL, // using absolute path, no hkey
  142. NULL);
  143. Status = NtOpenKey(
  144. phkResult,
  145. samDesired,
  146. &Obja);
  147. }
  148. } else {
  149. Status = STATUS_NO_MEMORY;
  150. }
  151. RtlFreeUnicodeString(&UsersHive);
  152. }
  153. if (NT_SUCCESS(Status)) {
  154. #if defined(LEAK_TRACK)
  155. if (g_RegLeakTraceInfo.bEnableLeakTrack) {
  156. (void) TrackObject(*phkResult);
  157. }
  158. #endif defined(LEAK_TRACK)
  159. // mark this key as a class key
  160. TagSpecialClassesHandle(phkResult);
  161. }
  162. return RtlNtStatusToDosError(Status);
  163. }
  164. BOOL InitializeClassesRoot()
  165. {
  166. if (!InitializeClassesEnumTable()) {
  167. return FALSE;
  168. }
  169. return TRUE;
  170. }
  171. BOOL CleanupClassesRoot(BOOL fOnlyThisThread)
  172. {
  173. //
  174. // Always remove enumeration states for this thread
  175. //
  176. return CleanupClassesEnumTable( fOnlyThisThread );
  177. }