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.

284 lines
6.4 KiB

  1. // Copyright (C) 1999 Microsoft Corporation
  2. //
  3. // Implementation of ICloneSecurityPrincipal::CopyDownlevelUserProperties
  4. //
  5. // sburns 5-14-99
  6. #include "headers.hxx"
  7. #include "resource.h"
  8. #include "common.hpp"
  9. #include "implmain.hpp"
  10. // caller must close the handle with SamCloseHandle
  11. HRESULT
  12. OpenSamUser(
  13. const String& samName,
  14. SAM_HANDLE domainSamHandle,
  15. SAM_HANDLE& resultSamHandle)
  16. {
  17. LOG_FUNCTION2(OpenSamUser, samName);
  18. ASSERT(!samName.empty());
  19. ASSERT(domainSamHandle != INVALID_HANDLE_VALUE);
  20. ASSERT(resultSamHandle == INVALID_HANDLE_VALUE);
  21. resultSamHandle = INVALID_HANDLE_VALUE;
  22. HRESULT hr = S_OK;
  23. ULONG* rids = 0;
  24. PSID_NAME_USE use = 0;
  25. do
  26. {
  27. LOG(L"Calling SamLookupNamesInDomain");
  28. UNICODE_STRING userName;
  29. ::RtlInitUnicodeString(&userName, samName.c_str());
  30. hr =
  31. NtStatusToHRESULT(
  32. ::SamLookupNamesInDomain(
  33. domainSamHandle,
  34. 1,
  35. &userName,
  36. &rids,
  37. &use));
  38. if (FAILED(hr))
  39. {
  40. SetComError(
  41. String::format(
  42. IDS_SAM_USER_NOT_FOUND,
  43. samName.c_str(),
  44. GetErrorMessage(hr).c_str()));
  45. break;
  46. }
  47. if (!use || *use != SidTypeUser) // prefix 111381
  48. {
  49. hr = Win32ToHresult(ERROR_NO_SUCH_USER);
  50. SetComError(
  51. String::format(
  52. IDS_SAM_NAME_IS_NOT_USER,
  53. samName.c_str()));
  54. break;
  55. }
  56. LOG(L"Calling SamOpenUser");
  57. hr =
  58. NtStatusToHRESULT(
  59. ::SamOpenUser(
  60. domainSamHandle,
  61. MAXIMUM_ALLOWED,
  62. rids[0],
  63. &resultSamHandle));
  64. if (FAILED(hr))
  65. {
  66. SetComError(
  67. String::format(
  68. IDS_OPEN_SAM_USER_FAILED,
  69. samName.c_str(),
  70. GetErrorMessage(hr).c_str()));
  71. break;
  72. }
  73. ASSERT(resultSamHandle != INVALID_HANDLE_VALUE);
  74. }
  75. while (0);
  76. if (rids)
  77. {
  78. ::SamFreeMemory(rids);
  79. }
  80. if (use)
  81. {
  82. ::SamFreeMemory(use);
  83. }
  84. return hr;
  85. }
  86. HRESULT
  87. CloneSecurityPrincipal::DoCopyDownlevelUserProperties(
  88. const String& srcSamName,
  89. const String& dstSamName,
  90. long flags)
  91. {
  92. LOG_FUNCTION(CloneSecurityPrincipal::DoCopyDownlevelUserProperties);
  93. if (srcSamName.empty())
  94. {
  95. SetComError(IDS_MISSING_SRC_SAM_NAME);
  96. return E_INVALIDARG;
  97. }
  98. if (flags)
  99. {
  100. // not used, should be 0
  101. SetComError(IDS_FLAGS_ARE_UNUSED);
  102. return E_INVALIDARG;
  103. }
  104. if (!connection || !connection->IsConnected())
  105. {
  106. SetComError(IDS_MUST_CONNECT_FIRST);
  107. return Win32ToHresult(ERROR_ONLY_IF_CONNECTED);
  108. };
  109. // At this point, the Computer objects contain the normalized
  110. // source and destination DC names, and their domains, and any
  111. // necessary authenticated connections to those DCs have been
  112. // established.
  113. HRESULT hr = S_OK;
  114. SAM_HANDLE userSamHandle = INVALID_HANDLE_VALUE;
  115. USER_ALL_INFORMATION* allInfo = 0;
  116. do
  117. {
  118. // get a handle to the source user
  119. hr =
  120. OpenSamUser(
  121. srcSamName,
  122. connection->srcDomainSamHandle,
  123. userSamHandle);
  124. BREAK_ON_FAILED_HRESULT(hr);
  125. LOG(L"Calling SamQueryInformationUser");
  126. hr =
  127. NtStatusToHRESULT(
  128. ::SamQueryInformationUser(
  129. userSamHandle,
  130. UserAllInformation,
  131. reinterpret_cast<void**>(&allInfo)));
  132. if (FAILED(hr))
  133. {
  134. SetComError(
  135. String::format(
  136. IDS_QUERY_SAM_USER_FAILED,
  137. srcSamName.c_str(),
  138. GetErrorMessage(hr).c_str()));
  139. break;
  140. }
  141. ::SamCloseHandle(userSamHandle);
  142. userSamHandle = INVALID_HANDLE_VALUE;
  143. // get a handle to the target user
  144. hr =
  145. OpenSamUser(
  146. dstSamName,
  147. connection->dstDomainSamHandle,
  148. userSamHandle);
  149. BREAK_ON_FAILED_HRESULT(hr);
  150. ULONG* rids = 0;
  151. PSID_NAME_USE use = 0;
  152. UNICODE_STRING userName;
  153. ::RtlInitUnicodeString(&userName, dstSamName.c_str());
  154. hr =
  155. NtStatusToHRESULT(
  156. ::SamLookupNamesInDomain(
  157. connection->dstDomainSamHandle,
  158. 1,
  159. &userName,
  160. &rids,
  161. &use));
  162. if (FAILED(hr))
  163. {
  164. SetComError(
  165. String::format(
  166. IDS_SAM_USER_NOT_FOUND,
  167. dstSamName.c_str(),
  168. GetErrorMessage(hr).c_str()));
  169. break;
  170. }
  171. if (*use != SidTypeUser)
  172. {
  173. hr = Win32ToHresult(ERROR_NO_SUCH_USER);
  174. SetComError(
  175. String::format(
  176. IDS_SAM_NAME_IS_NOT_USER,
  177. dstSamName.c_str()));
  178. break;
  179. }
  180. allInfo->WhichFields =
  181. USER_ALL_FULLNAME
  182. | USER_ALL_ADMINCOMMENT
  183. | USER_ALL_USERCOMMENT
  184. | USER_ALL_HOMEDIRECTORY
  185. | USER_ALL_HOMEDIRECTORYDRIVE
  186. | USER_ALL_SCRIPTPATH
  187. | USER_ALL_PROFILEPATH
  188. | USER_ALL_WORKSTATIONS
  189. | USER_ALL_LOGONHOURS
  190. // USER_ALL_BADPASSWORDCOUNT
  191. //| USER_ALL_PASSWORDCANCHANGE
  192. //| USER_ALL_PASSWORDMUSTCHANGE
  193. //| USER_ALL_USERACCOUNTCONTROL
  194. // this is the reason for all this nonsense
  195. | USER_ALL_PARAMETERS
  196. | USER_ALL_COUNTRYCODE
  197. | USER_ALL_CODEPAGE
  198. //| USER_ALL_PASSWORDEXPIRED*/
  199. ;
  200. if( *rids != 500 )
  201. allInfo->WhichFields |= USER_ALL_ACCOUNTEXPIRES;
  202. if (rids)
  203. {
  204. ::SamFreeMemory(rids);
  205. }
  206. if (use)
  207. {
  208. ::SamFreeMemory(use);
  209. }
  210. // @@ why is user cannot change password not transferring?
  211. LOG(L"Calling SamSetInformationUser");
  212. hr =
  213. NtStatusToHRESULT(
  214. ::SamSetInformationUser(
  215. userSamHandle,
  216. UserAllInformation,
  217. allInfo));
  218. if (FAILED(hr))
  219. {
  220. SetComError(
  221. String::format(
  222. IDS_SET_SAM_USER_FAILED,
  223. dstSamName.c_str(),
  224. GetErrorMessage(hr).c_str()));
  225. break;
  226. }
  227. }
  228. while (0);
  229. if (userSamHandle != INVALID_HANDLE_VALUE)
  230. {
  231. ::SamCloseHandle(userSamHandle);
  232. }
  233. if (allInfo)
  234. {
  235. ::SamFreeMemory(allInfo);
  236. }
  237. return hr;
  238. }