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.

430 lines
13 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 2000
  4. Module Name:
  5. usrinfo.cxx
  6. Abstract:
  7. This module contains the implementation of the members of the class
  8. CUsrInfo which is used to store and manipulate pertinent information
  9. about the logged on user, e.g. the HOMEDIR path, the user name,
  10. logon domain, etc.
  11. Author:
  12. Rahul Thombre (RahulTh) 2/28/2000
  13. Revision History:
  14. 2/28/2000 RahulTh Created this module.
  15. --*/
  16. #include "fdeploy.hxx"
  17. CUsrInfo::CUsrInfo () : _pwszNameBuf (NULL),
  18. _pwszUserName (NULL),
  19. _pwszDomain (NULL),
  20. _pwszHomeDir (NULL),
  21. _bAttemptedGetUserName (FALSE),
  22. _bAttemptedGetHomeDir (FALSE),
  23. _StatusUserName (ERROR_SUCCESS),
  24. _StatusHomeDir (ERROR_SUCCESS),
  25. _pPlanningModeContext (NULL)
  26. {
  27. }
  28. CUsrInfo::~CUsrInfo ()
  29. {
  30. ResetMembers();
  31. }
  32. //+--------------------------------------------------------------------------
  33. //
  34. // Member: CUsrInfo::ResetMembers
  35. //
  36. // Synopsis: Resets the member variables to their default values.
  37. //
  38. // Arguments: none.
  39. //
  40. // Returns: nothing.
  41. //
  42. // History: 12/17/2000 RahulTh created
  43. //
  44. // Notes: This function was added to facilitate the reinitialization
  45. // of the member functions of global variables. This is necessary
  46. // for consecutive runs of folder redirection (if fdeploy.dll) does
  47. // not get reloaded for some reason and the constructors for the
  48. // global variables are not invoked. This can lead to strange
  49. // undesirable results especially if the two consecutive runs are
  50. // for two different users.
  51. //
  52. //---------------------------------------------------------------------------
  53. void CUsrInfo::ResetMembers(void)
  54. {
  55. if (_pwszNameBuf)
  56. {
  57. delete [] _pwszNameBuf;
  58. _pwszNameBuf = NULL;
  59. }
  60. //
  61. // Note: _pwszUserName and _pwszDomain are const pointers pointing to the
  62. // domain and user name within _pwszNameBuf. So there is no need to
  63. // delete them here.
  64. //
  65. _pwszUserName = _pwszDomain = NULL;
  66. if (_pwszHomeDir)
  67. {
  68. delete [] _pwszHomeDir;
  69. _pwszHomeDir = NULL;
  70. }
  71. _bAttemptedGetHomeDir = _bAttemptedGetUserName = FALSE; // fixing bug 590015
  72. _StatusUserName = _StatusHomeDir = ERROR_SUCCESS;
  73. _pPlanningModeContext = NULL;
  74. return;
  75. }
  76. //+--------------------------------------------------------------------------
  77. //
  78. // Member: CUsrInfo::GetUserName
  79. //
  80. // Synopsis: Retrieves the name of the logged on user.
  81. //
  82. // Arguments: [out] DWORD : StatusCode : the status code of the operation
  83. //
  84. // Returns: NULL : if the user name could not be obtained.
  85. // const pointer to a string containing the username otherwise.
  86. //
  87. // History: 2/28/2000 RahulTh created
  88. //
  89. // Notes:
  90. //
  91. //---------------------------------------------------------------------------
  92. const WCHAR * CUsrInfo::GetUserName (OUT DWORD & StatusCode)
  93. {
  94. ULONG ulNameLen;
  95. BOOL bStatus;
  96. WCHAR * wszPtr = NULL;
  97. //
  98. // In planning mode, if no user name was specified because the
  99. // caller targeted a SOM and not a user, we will return NULL
  100. // with a success status to indicate this
  101. //
  102. if ( _pPlanningModeContext &&
  103. ! _pPlanningModeContext->_pRsopTarget->pwszAccountName )
  104. {
  105. StatusCode = ERROR_SUCCESS;
  106. return NULL;
  107. }
  108. if (_bAttemptedGetUserName)
  109. goto GetUserName_CleanupAndQuit;
  110. _bAttemptedGetUserName = TRUE;
  111. for (ulNameLen = UNLEN + 1;;)
  112. {
  113. if (_pwszNameBuf)
  114. {
  115. delete [] _pwszNameBuf;
  116. _pwszNameBuf = NULL;
  117. }
  118. _pwszNameBuf = new WCHAR [ulNameLen];
  119. if (! _pwszNameBuf)
  120. {
  121. _StatusUserName = ERROR_OUTOFMEMORY;
  122. goto GetUserName_CleanupAndQuit;
  123. }
  124. //
  125. // In non-planning mode, we can use standard system api's
  126. // to retrieve a sam compatible user name ("domain\username").
  127. //
  128. if ( ! _pPlanningModeContext )
  129. {
  130. bStatus = GetUserNameEx (NameSamCompatible, _pwszNameBuf, &ulNameLen);
  131. if (!bStatus)
  132. _StatusUserName = GetLastError();
  133. }
  134. else
  135. {
  136. _StatusUserName = GetPlanningModeSamCompatibleUserName(
  137. _pwszNameBuf,
  138. &ulNameLen);
  139. }
  140. if (ERROR_MORE_DATA == _StatusUserName)
  141. continue;
  142. else if (ERROR_SUCCESS == _StatusUserName)
  143. break;
  144. else
  145. goto GetUserName_CleanupAndQuit;
  146. }
  147. wszPtr = wcschr (_pwszNameBuf, L'\\');
  148. // Make sure it is in the form domain\username
  149. if (!wszPtr || L'\0' == wszPtr[1] || wszPtr == _pwszNameBuf)
  150. {
  151. _StatusUserName = ERROR_NO_SUCH_USER;
  152. goto GetUserName_CleanupAndQuit;
  153. }
  154. //
  155. // If we are here, we already have a SAM compatible name, in the form of
  156. // domain\username. Now we just need to make sure that _pwszUserName
  157. // and _pwszDomain point to the right places in the string.
  158. //
  159. // First NULL out the \ so that the string is split into the domain part
  160. // and the username part
  161. //
  162. *wszPtr = L'\0';
  163. // Assign the proper pointers
  164. _pwszUserName = &wszPtr[1];
  165. _pwszDomain = _pwszNameBuf;
  166. // Record success
  167. _StatusUserName = ERROR_SUCCESS;
  168. GetUserName_CleanupAndQuit:
  169. StatusCode = _StatusUserName;
  170. return _pwszUserName;
  171. }
  172. //+--------------------------------------------------------------------------
  173. //
  174. // Member: CUsrInfo::GetHomeDir
  175. //
  176. // Synopsis: Retrieves the homedir of the logged on user, if defined.
  177. //
  178. // Arguments: [out] DWORD : StatusCode : the status code of the operation
  179. //
  180. // Returns: NULL : if homedir is not defined or the information cannot be
  181. // obtained.
  182. // const pointer to a string containing the homedir otherwise.
  183. //
  184. // History: 2/28/2000 RahulTh created
  185. //
  186. // Notes: If the homedir is not set for the user, then this function
  187. // returns NULL, but the StatusCode is set to ERROR_SUCCESS
  188. // That is how we differentiate between the case where there
  189. // is no homedir because there was an error trying to obtain it
  190. // and the case where there was no error but the homedir has not
  191. // been set for the user.
  192. //
  193. //---------------------------------------------------------------------------
  194. const WCHAR * CUsrInfo::GetHomeDir (OUT DWORD & StatusCode)
  195. {
  196. const WCHAR * pwszUName = NULL;
  197. PUSER_INFO_2 pUserInfo = NULL;
  198. NET_API_STATUS netStatus = NERR_Success;
  199. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  200. if (_bAttemptedGetHomeDir)
  201. goto GetHomeDir_CleanupAndQuit;
  202. _bAttemptedGetHomeDir = TRUE;
  203. // Get the user name and domain so that we can query for the homedir.
  204. if (_bAttemptedGetUserName)
  205. {
  206. _StatusHomeDir = _StatusUserName;
  207. pwszUName = _pwszUserName;
  208. }
  209. else
  210. {
  211. pwszUName = this->GetUserName (_StatusHomeDir);
  212. }
  213. if (NULL == pwszUName || ERROR_SUCCESS != _StatusHomeDir)
  214. goto GetHomeDir_CleanupAndQuit;
  215. //
  216. // If we are here, we have the user name and the domain info.
  217. // So now we try to get the user's home directory from the user
  218. // object.
  219. //
  220. // First get a domain controller
  221. //
  222. DebugMsg ((DM_VERBOSE, IDS_QUERYDSFORHOMEDIR, _pwszUserName));
  223. _StatusHomeDir = DsGetDcName (NULL, _pwszDomain, NULL, NULL,
  224. DS_DIRECTORY_SERVICE_REQUIRED, &pDCInfo);
  225. if (NO_ERROR != _StatusHomeDir)
  226. goto GetHomeDir_CleanupAndQuit;
  227. netStatus = NetUserGetInfo (pDCInfo->DomainControllerName,
  228. pwszUName,
  229. 2,
  230. (LPBYTE *) &pUserInfo
  231. );
  232. switch (netStatus)
  233. {
  234. case NERR_Success:
  235. break;
  236. case NERR_InvalidComputer:
  237. _StatusHomeDir = ERROR_INVALID_COMPUTERNAME;
  238. goto GetHomeDir_CleanupAndQuit;
  239. break;
  240. case NERR_UserNotFound:
  241. _StatusHomeDir = ERROR_NO_SUCH_USER;
  242. goto GetHomeDir_CleanupAndQuit;
  243. break;
  244. case ERROR_ACCESS_DENIED:
  245. _StatusHomeDir = ERROR_ACCESS_DENIED;
  246. goto GetHomeDir_CleanupAndQuit;
  247. break;
  248. default:
  249. //
  250. // We encountered some other unexpected network error. Just translate it to a
  251. // generic error code.
  252. //
  253. _StatusHomeDir = ERROR_UNEXP_NET_ERR;
  254. goto GetHomeDir_CleanupAndQuit;
  255. break;
  256. }
  257. //
  258. // If we are here, we managed to get the user info.
  259. // Now, check if the user has a home directory
  260. //
  261. // Note: If the user does not have a home directory set, we return
  262. // NULL, but _StatusHomeDir is set to ERROR_SUCCESS
  263. _StatusHomeDir = ERROR_SUCCESS;
  264. if (pUserInfo->usri2_home_dir && L'\0' != pUserInfo->usri2_home_dir)
  265. {
  266. size_t homeDirSize = lstrlen (pUserInfo->usri2_home_dir) + 1;
  267. _pwszHomeDir = new WCHAR [homeDirSize];
  268. if (_pwszHomeDir)
  269. {
  270. (void) StringCchCopy(_pwszHomeDir, homeDirSize, pUserInfo->usri2_home_dir);
  271. DebugMsg ((DM_VERBOSE, IDS_OBTAINED_HOMEDIR, _pwszHomeDir));
  272. }
  273. else
  274. {
  275. _StatusHomeDir = ERROR_OUTOFMEMORY;
  276. }
  277. }
  278. GetHomeDir_CleanupAndQuit:
  279. // Cleanup
  280. if (pDCInfo)
  281. NetApiBufferFree ((LPVOID)pDCInfo);
  282. if (pUserInfo)
  283. NetApiBufferFree ((LPVOID)pUserInfo);
  284. // Set return values and quit
  285. StatusCode = _StatusHomeDir;
  286. if (ERROR_SUCCESS != StatusCode)
  287. {
  288. DebugMsg ((DM_VERBOSE, IDS_FAILED_GETHOMEDIR));
  289. }
  290. return (const WCHAR *) _pwszHomeDir;
  291. }
  292. //+--------------------------------------------------------------------------
  293. //
  294. // Member: CUsrInfo::SetPlanningModeContext
  295. //
  296. // Synopsis: Set's this object's planning mode information -- setting
  297. // this causes this object to believe it is in planning mode
  298. //
  299. // Arguments: [in] CRsopContext* pRsopContext : pointer to planning mode
  300. // context object. The lifetime of the context object is not
  301. // owned by this object -- it does not need to be refcounted
  302. // before calling this method.
  303. //
  304. // History: 7/6/2000 AdamEd created
  305. //
  306. //---------------------------------------------------------------------------
  307. void CUsrInfo::SetPlanningModeContext( CRsopContext* pRsopContext )
  308. {
  309. _pPlanningModeContext = pRsopContext;
  310. }
  311. //+--------------------------------------------------------------------------
  312. //
  313. // Member: CUsrInfo::GetPlanningModeSamCompatibleUserName
  314. //
  315. // Synopsis: Retrieves the user name of the user specified in this
  316. // object's planning mode context
  317. //
  318. // Arguments: [in] WCHAR* : pwszUserName : buffer in which to store
  319. // the same compatbile user name ("domain\username" format).
  320. // [in, out] : pcchUserName : length, in chars, including
  321. // the null terminator, of the pwszUserName buffer.
  322. // On output, the it is the number of characters
  323. // needed in the buffer, including the null terminator
  324. // Returns: NULL : ERROR_SUCCESS if the user name is successfully
  325. // copied to the pwszUserName buffer, ERROR_MORE_DATA otherwise
  326. //
  327. // History: 7/6/2000 AdamEd created
  328. //
  329. //---------------------------------------------------------------------------
  330. DWORD CUsrInfo::GetPlanningModeSamCompatibleUserName( WCHAR* pwszUserName, ULONG* pcchUserName )
  331. {
  332. DWORD Status;
  333. WCHAR* pwszUserNameSource;
  334. ULONG ulActualLen;
  335. //
  336. // The interface to this method is designed to mirror that of the
  337. // GetUserNameEx api to simplify code that executes in both planning
  338. // and normal modes.
  339. //
  340. //
  341. // In planning mode, we retrieve the user name from the RSoP context.
  342. // This RSoP context has the user name in sam compatible form.
  343. //
  344. pwszUserNameSource = _pPlanningModeContext->_pRsopTarget->pwszAccountName;
  345. ulActualLen = lstrlen( pwszUserNameSource )+1;
  346. //
  347. // If we have enough space, copy the string
  348. //
  349. if ( ulActualLen <= *pcchUserName )
  350. {
  351. (void) StringCchCopy( pwszUserName, *pcchUserName, pwszUserNameSource );
  352. Status = ERROR_SUCCESS;
  353. }
  354. else
  355. {
  356. Status = ERROR_MORE_DATA;
  357. }
  358. *pcchUserName = ulActualLen;
  359. return Status;
  360. }