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.

1661 lines
43 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: envvar.c
  3. *
  4. * Copyright (c) 1992, Microsoft Corporation
  5. *
  6. * Sets environment variables.
  7. *
  8. * History:
  9. * 2-25-92 JohanneC Created -
  10. *
  11. \***************************************************************************/
  12. #include "msgina.h"
  13. #ifdef _X86_
  14. #include "i386\oemhard.h"
  15. #endif
  16. #pragma hdrstop
  17. BOOL ProcessCommand(LPTSTR lpStart, PVOID *pEnv);
  18. BOOL ProcessSetCommand(LPTSTR lpStart, PVOID *pEnv);
  19. LPTSTR ProcessAutoexecPath(PVOID *pEnv, LPTSTR lpValue, DWORD cb);
  20. LONG AddNetworkConnection(PGLOBALS pGlobals, LPNETRESOURCE lpNetResource);
  21. BOOL UpdateUserEnvironmentVars( PVOID *pEnv );
  22. #ifdef _X86_
  23. BOOL IsPathIncludeRemovable(LPTSTR lpValue);
  24. #endif
  25. BOOL GetLUIDDeviceMapsEnabled( VOID );
  26. #define KEY_NAME TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment")
  27. //
  28. // Max environment variable length
  29. //
  30. #define MAX_VALUE_LEN 1024
  31. #define BSLASH TEXT('\\')
  32. #define COLON TEXT(':')
  33. //
  34. // These two globals implement ref counting on
  35. // pGlobals->UserProcessData->hCurrentUser (418628)
  36. // managed by OpenHKeyCurrentUser/CloseHKeyCurrentUser below
  37. //
  38. RTL_CRITICAL_SECTION g_csHKCU;
  39. ULONG g_ulHKCURef;
  40. BOOL
  41. InitHKeyCurrentUserSupport(
  42. )
  43. {
  44. NTSTATUS Status ;
  45. Status = RtlInitializeCriticalSection( &g_csHKCU );
  46. if ( !NT_SUCCESS( Status ) )
  47. {
  48. DebugLog((DEB_ERROR, "InitHKeyCurrentUserSupport failed to init its lock, error = 0x%08X\n", Status));
  49. return FALSE;
  50. }
  51. g_ulHKCURef = 0;
  52. return TRUE;
  53. }
  54. VOID
  55. CleanupHKeyCurrentUserSupport(
  56. )
  57. {
  58. RtlDeleteCriticalSection( &g_csHKCU );
  59. }
  60. /***************************************************************************\
  61. * OpenHKeyCurrentUser
  62. *
  63. * Opens HKeyCurrentUser to point at the current logged on user's profile.
  64. *
  65. * Returns TRUE on success, FALSE on failure
  66. *
  67. * History:
  68. * 06-16-92 Davidc Created
  69. *
  70. \***************************************************************************/
  71. BOOL
  72. OpenHKeyCurrentUser(
  73. PGLOBALS pGlobals
  74. )
  75. {
  76. HANDLE ImpersonationHandle;
  77. BOOL Result;
  78. NTSTATUS Status ;
  79. //
  80. // Get in the correct context before we reference the registry
  81. //
  82. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  83. if (ImpersonationHandle == NULL) {
  84. DebugLog((DEB_ERROR, "OpenHKeyCurrentUser failed to impersonate user"));
  85. return(FALSE);
  86. }
  87. RtlEnterCriticalSection( &g_csHKCU );
  88. if (g_ulHKCURef == 0)
  89. {
  90. Status = RtlOpenCurrentUser(
  91. MAXIMUM_ALLOWED,
  92. &pGlobals->UserProcessData.hCurrentUser );
  93. }
  94. g_ulHKCURef++;
  95. RtlLeaveCriticalSection( &g_csHKCU );
  96. //
  97. // Return to our own context
  98. //
  99. Result = StopImpersonating(ImpersonationHandle);
  100. ASSERT(Result);
  101. return(TRUE);
  102. }
  103. /***************************************************************************\
  104. * CloseHKeyCurrentUser
  105. *
  106. * Closes HKEY_CURRENT_USER.
  107. * Any registry reference will automatically re-open it, so this is
  108. * only a token gesture - but it allows the registry hive to be unloaded.
  109. *
  110. * Returns nothing
  111. *
  112. * History:
  113. * 06-16-92 Davidc Created
  114. *
  115. \***************************************************************************/
  116. VOID
  117. CloseHKeyCurrentUser(
  118. PGLOBALS pGlobals
  119. )
  120. {
  121. RtlEnterCriticalSection( &g_csHKCU );
  122. if (g_ulHKCURef > 0)
  123. {
  124. if (--g_ulHKCURef == 0)
  125. {
  126. NtClose( pGlobals->UserProcessData.hCurrentUser );
  127. pGlobals->UserProcessData.hCurrentUser = NULL ;
  128. }
  129. }
  130. RtlLeaveCriticalSection( &g_csHKCU );
  131. }
  132. /***************************************************************************\
  133. * SetUserEnvironmentVariable
  134. *
  135. *
  136. * History:
  137. * 2-28-92 Johannec Created
  138. *
  139. \***************************************************************************/
  140. BOOL
  141. SetUserEnvironmentVariable(
  142. PVOID *pEnv,
  143. LPTSTR lpVariable,
  144. LPTSTR lpValue,
  145. BOOL bOverwrite
  146. )
  147. {
  148. NTSTATUS Status;
  149. UNICODE_STRING Name, Value;
  150. DWORD cb;
  151. TCHAR szValue[1024];
  152. if (!*pEnv || !lpVariable || !*lpVariable) {
  153. return(FALSE);
  154. }
  155. RtlInitUnicodeString(&Name, lpVariable);
  156. cb = 1024;
  157. Value.Buffer = Alloc(sizeof(TCHAR)*cb);
  158. if (Value.Buffer) {
  159. Value.Length = (USHORT)cb;
  160. Value.MaximumLength = (USHORT)cb;
  161. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  162. Free(Value.Buffer);
  163. if ( NT_SUCCESS(Status) && !bOverwrite) {
  164. return(TRUE);
  165. }
  166. }
  167. if (lpValue && *lpValue) {
  168. //
  169. // Special case TEMP and TMP and shorten the path names
  170. //
  171. if ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
  172. (!lstrcmpi(lpVariable, TEXT("TMP")))) {
  173. if (!GetShortPathName (lpValue, szValue, 1024)) {
  174. lstrcpyn (szValue, lpValue, 1024);
  175. }
  176. } else {
  177. lstrcpyn (szValue, lpValue, 1024);
  178. }
  179. RtlInitUnicodeString(&Value, szValue);
  180. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  181. }
  182. else {
  183. Status = RtlSetEnvironmentVariable(pEnv, &Name, NULL);
  184. }
  185. if (NT_SUCCESS(Status)) {
  186. return(TRUE);
  187. }
  188. return(FALSE);
  189. }
  190. /***************************************************************************\
  191. * ExpandUserEnvironmentStrings
  192. *
  193. * History:
  194. * 2-28-92 Johannec Created
  195. *
  196. \***************************************************************************/
  197. DWORD
  198. ExpandUserEnvironmentStrings(
  199. PVOID pEnv,
  200. LPTSTR lpSrc,
  201. LPTSTR lpDst,
  202. DWORD nSize
  203. )
  204. {
  205. NTSTATUS Status;
  206. UNICODE_STRING Source, Destination;
  207. ULONG Length;
  208. RtlInitUnicodeString( &Source, lpSrc );
  209. Destination.Buffer = lpDst;
  210. Destination.Length = 0;
  211. Destination.MaximumLength = (USHORT)nSize;
  212. Length = 0;
  213. Status = RtlExpandEnvironmentStrings_U( pEnv,
  214. (PUNICODE_STRING)&Source,
  215. (PUNICODE_STRING)&Destination,
  216. &Length
  217. );
  218. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) {
  219. return( Length );
  220. }
  221. else {
  222. return( 0 );
  223. }
  224. }
  225. /***************************************************************************\
  226. * BuildEnvironmentPath
  227. *
  228. *
  229. * History:
  230. * 2-28-92 Johannec Created
  231. *
  232. \***************************************************************************/
  233. BOOL BuildEnvironmentPath(PVOID *pEnv,
  234. LPTSTR lpPathVariable,
  235. LPTSTR lpPathValue)
  236. {
  237. NTSTATUS Status;
  238. UNICODE_STRING Name;
  239. UNICODE_STRING Value;
  240. TCHAR lpTemp[1025];
  241. DWORD cb;
  242. if (!*pEnv) {
  243. return(FALSE);
  244. }
  245. RtlInitUnicodeString(&Name, lpPathVariable);
  246. cb = 1024;
  247. Value.Buffer = Alloc(sizeof(TCHAR)*cb);
  248. if (!Value.Buffer) {
  249. return(FALSE);
  250. }
  251. Value.Length = (USHORT)(sizeof(TCHAR) * cb);
  252. Value.MaximumLength = (USHORT)(sizeof(TCHAR) * cb);
  253. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  254. if (!NT_SUCCESS(Status)) {
  255. Free(Value.Buffer);
  256. Value.Length = 0;
  257. *lpTemp = 0;
  258. }
  259. if (Value.Length) {
  260. lstrcpy(lpTemp, Value.Buffer);
  261. if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') ) {
  262. lstrcat(lpTemp, TEXT(";"));
  263. }
  264. Free(Value.Buffer);
  265. }
  266. if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb)) {
  267. lstrcat(lpTemp, lpPathValue);
  268. RtlInitUnicodeString(&Value, lpTemp);
  269. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  270. }
  271. if (NT_SUCCESS(Status)) {
  272. return(TRUE);
  273. }
  274. return(FALSE);
  275. }
  276. /***************************************************************************\
  277. * SetEnvironmentVariables
  278. *
  279. * Reads the user-defined environment variables from the user registry
  280. * and adds them to the environment block at pEnv.
  281. *
  282. * History:
  283. * 2-28-92 Johannec Created
  284. *
  285. \***************************************************************************/
  286. BOOL
  287. SetEnvironmentVariables(
  288. PGLOBALS pGlobals,
  289. LPTSTR pEnvVarSubkey,
  290. PVOID *pEnv
  291. )
  292. {
  293. TCHAR lpValueName[MAX_PATH];
  294. PWCH lpDataBuffer;
  295. DWORD cbDataBuffer;
  296. PWCH lpData;
  297. LPTSTR lpExpandedValue = NULL;
  298. DWORD cbValueName = MAX_PATH;
  299. DWORD cbData;
  300. DWORD dwType;
  301. DWORD dwIndex = 0;
  302. HKEY hkey;
  303. BOOL bResult;
  304. /*
  305. * Open registry key to access USER environment variables.
  306. */
  307. if (!OpenHKeyCurrentUser(pGlobals)) {
  308. DebugLog((DEB_ERROR, "SetEnvironmentVariables: Failed to open HKeyCurrentUser"));
  309. return(FALSE);
  310. }
  311. if (RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser, pEnvVarSubkey, 0, KEY_READ, &hkey)) {
  312. CloseHKeyCurrentUser(pGlobals);
  313. return(FALSE);
  314. }
  315. cbDataBuffer = 4096;
  316. lpDataBuffer = Alloc(sizeof(TCHAR)*cbDataBuffer);
  317. if (lpDataBuffer == NULL) {
  318. DebugLog((DEB_ERROR, "SetEnvironmentVariables: Failed to allocate %d bytes", cbDataBuffer));
  319. CloseHKeyCurrentUser(pGlobals);
  320. RegCloseKey(hkey);
  321. return(FALSE);
  322. }
  323. lpData = lpDataBuffer;
  324. cbData = sizeof(TCHAR)*cbDataBuffer;
  325. bResult = TRUE;
  326. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  327. (LPBYTE)lpData, &cbData)) {
  328. if (cbValueName) {
  329. //
  330. // Limit environment variable length
  331. //
  332. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  333. if (dwType == REG_SZ) {
  334. //
  335. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  336. // their values apppended to the system path.
  337. //
  338. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  339. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  340. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  341. BuildEnvironmentPath(pEnv, lpValueName, lpData);
  342. }
  343. else {
  344. //
  345. // the other environment variables are just set.
  346. //
  347. SetUserEnvironmentVariable(pEnv, lpValueName, lpData, TRUE);
  348. }
  349. }
  350. }
  351. dwIndex++;
  352. cbData = cbDataBuffer;
  353. cbValueName = MAX_PATH;
  354. }
  355. dwIndex = 0;
  356. cbData = cbDataBuffer;
  357. cbValueName = MAX_PATH;
  358. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  359. (LPBYTE)lpData, &cbData)) {
  360. if (cbValueName) {
  361. //
  362. // Limit environment variable length
  363. //
  364. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  365. if (dwType == REG_EXPAND_SZ) {
  366. DWORD cb, cbNeeded;
  367. cb = 1024;
  368. lpExpandedValue = Alloc(sizeof(TCHAR)*cb);
  369. if (lpExpandedValue) {
  370. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, lpData, lpExpandedValue, cb);
  371. if (cbNeeded > cb) {
  372. Free(lpExpandedValue);
  373. cb = cbNeeded;
  374. lpExpandedValue = Alloc(sizeof(TCHAR)*cb);
  375. if (lpExpandedValue) {
  376. ExpandUserEnvironmentStrings(*pEnv, lpData, lpExpandedValue, cb);
  377. }
  378. }
  379. }
  380. if (lpExpandedValue == NULL) {
  381. bResult = FALSE;
  382. break;
  383. }
  384. //
  385. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  386. // their values apppended to the system path.
  387. //
  388. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  389. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  390. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  391. BuildEnvironmentPath(pEnv, lpValueName, lpExpandedValue);
  392. }
  393. else {
  394. //
  395. // the other environment variables are just set.
  396. //
  397. SetUserEnvironmentVariable(pEnv, lpValueName, lpExpandedValue, TRUE);
  398. }
  399. Free(lpExpandedValue);
  400. }
  401. }
  402. dwIndex++;
  403. cbData = cbDataBuffer;
  404. cbValueName = MAX_PATH;
  405. }
  406. Free(lpDataBuffer);
  407. RegCloseKey(hkey);
  408. CloseHKeyCurrentUser(pGlobals);
  409. return(bResult);
  410. }
  411. /***************************************************************************\
  412. * IsUNCPath
  413. *
  414. * History:
  415. * 2-28-92 Johannec Created
  416. *
  417. \***************************************************************************/
  418. BOOL IsUNCPath(LPTSTR lpPath)
  419. {
  420. if (lpPath[0] == BSLASH && lpPath[1] == BSLASH) {
  421. return(TRUE);
  422. }
  423. return(FALSE);
  424. }
  425. /***************************************************************************\
  426. * SetHomeDirectoryEnvVars
  427. *
  428. * History:
  429. * 2-28-92 Johannec Created
  430. *
  431. \***************************************************************************/
  432. BOOL
  433. SetHomeDirectoryEnvVars(
  434. PVOID *pEnv,
  435. LPTSTR lpHomeDirectory,
  436. LPTSTR lpHomeDrive,
  437. LPTSTR lpHomeShare,
  438. LPTSTR lpHomePath,
  439. BOOL * pfDeepShare
  440. )
  441. {
  442. TCHAR cTmp;
  443. LPTSTR lpHomeTmp;
  444. BOOL bFoundFirstBSlash = FALSE;
  445. if (!*lpHomeDirectory) {
  446. return(FALSE);
  447. }
  448. *pfDeepShare = FALSE;
  449. if (IsUNCPath(lpHomeDirectory)) {
  450. lpHomeTmp = lpHomeDirectory + 2;
  451. while (*lpHomeTmp) {
  452. if (*lpHomeTmp == BSLASH) {
  453. if (bFoundFirstBSlash) {
  454. break;
  455. }
  456. bFoundFirstBSlash = TRUE;
  457. }
  458. lpHomeTmp++;
  459. }
  460. if (*lpHomeTmp) {
  461. lstrcpy(lpHomePath, lpHomeTmp);
  462. *pfDeepShare = TRUE;
  463. }
  464. else {
  465. *lpHomePath = BSLASH;
  466. *(lpHomePath+1) = 0;
  467. }
  468. cTmp = *lpHomeTmp;
  469. *lpHomeTmp = (TCHAR)0;
  470. lstrcpy(lpHomeShare, lpHomeDirectory);
  471. *lpHomeTmp = cTmp;
  472. //
  473. // If no home drive specified, than default to z:
  474. //
  475. if (!*lpHomeDrive) {
  476. lstrcpy(lpHomeDrive, TEXT("Z:"));
  477. }
  478. }
  479. else { // local home directory
  480. *lpHomeShare = 0; // no home share
  481. cTmp = lpHomeDirectory[2];
  482. lpHomeDirectory[2] = (TCHAR)0;
  483. lstrcpy(lpHomeDrive, lpHomeDirectory);
  484. lpHomeDirectory[2] = cTmp;
  485. lstrcpy(lpHomePath, lpHomeDirectory + 2);
  486. }
  487. SetUserEnvironmentVariable(pEnv, HOMEDRIVE_VARIABLE, lpHomeDrive, TRUE);
  488. SetUserEnvironmentVariable(pEnv, HOMESHARE_VARIABLE, lpHomeShare, TRUE);
  489. SetUserEnvironmentVariable(pEnv, HOMEPATH_VARIABLE, lpHomePath, TRUE);
  490. return TRUE;
  491. }
  492. /***************************************************************************\
  493. * UpdateHomeVarsInVolatileEnv
  494. *
  495. * Sets the HOMEDRIVE, HOMEPATH and HOMESHARE variables in the user's home
  496. * volatile environment so that SHGetFolderPath is able to expand these
  497. * variables
  498. *
  499. * History:
  500. * 6-5-2000 RahulTh Created
  501. *
  502. \***************************************************************************/
  503. VOID
  504. UpdateHomeVarsInVolatileEnv (
  505. PGLOBALS pGlobals,
  506. LPTSTR lpHomeDrive,
  507. LPTSTR lpHomeShare,
  508. LPTSTR lpHomePath
  509. )
  510. {
  511. BOOL bOpenedHKCU;
  512. HANDLE ImpersonationHandle = NULL;
  513. HKEY hUserVolatileEnv = NULL;
  514. LONG lResult;
  515. bOpenedHKCU = OpenHKeyCurrentUser (pGlobals);
  516. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  517. if (ImpersonationHandle != NULL) {
  518. //
  519. // See the registry value to see whether we should really try to map
  520. // the whole directory or just map to the root..
  521. //
  522. if ((pGlobals->UserProcessData).hCurrentUser) {
  523. lResult = RegOpenKeyEx((pGlobals->UserProcessData).hCurrentUser, L"Volatile Environment", 0, KEY_READ | KEY_WRITE, &hUserVolatileEnv);
  524. if (lResult == ERROR_SUCCESS) {
  525. RegSetValueEx (hUserVolatileEnv,
  526. HOMEDRIVE_VARIABLE,
  527. 0,
  528. REG_SZ,
  529. (LPBYTE) lpHomeDrive,
  530. (lstrlen (lpHomeDrive) + 1) * sizeof (TCHAR));
  531. RegSetValueEx (hUserVolatileEnv,
  532. HOMESHARE_VARIABLE,
  533. 0,
  534. REG_SZ,
  535. (LPBYTE) lpHomeShare,
  536. (lstrlen (lpHomeShare) + 1) * sizeof (TCHAR));
  537. RegSetValueEx (hUserVolatileEnv,
  538. HOMEPATH_VARIABLE,
  539. 0,
  540. REG_SZ,
  541. (LPBYTE) lpHomePath,
  542. (lstrlen (lpHomePath) + 1) * sizeof (TCHAR));
  543. RegCloseKey(hUserVolatileEnv);
  544. }
  545. }
  546. //
  547. // Revert to being 'ourself'
  548. //
  549. if (!StopImpersonating(ImpersonationHandle)) {
  550. DebugLog((DEB_ERROR, "UpdateHomeVarsInVolatileEnv : Failed to revert to self"));
  551. }
  552. //
  553. // Set it to NULL
  554. //
  555. ImpersonationHandle = NULL;
  556. }
  557. else {
  558. DebugLog((DEB_ERROR, "UpdateHomeVarsInVolatileEnv : Failed to impersonate user"));
  559. }
  560. if (bOpenedHKCU)
  561. CloseHKeyCurrentUser (pGlobals);
  562. }
  563. /***************************************************************************\
  564. * ChangeToHomeDirectory
  565. *
  566. * Sets the current directory to the user's home directory. If this fails
  567. * tries to set to the directory in the following order:
  568. * 1. home directory
  569. * 2. c:\users\default
  570. * 3. c:\users
  571. * 4. \ (root)
  572. * 5. leaves directory as is i.e. the present current directory
  573. *
  574. * History:
  575. * 2-28-92 Johannec Created
  576. *
  577. \***************************************************************************/
  578. VOID
  579. ChangeToHomeDirectory(
  580. PGLOBALS pGlobals,
  581. PVOID *pEnv,
  582. LPTSTR lpHomeDir,
  583. LPTSTR lpHomeDrive,
  584. LPTSTR lpHomeShare,
  585. LPTSTR lpHomePath,
  586. LPTSTR lpOldDir,
  587. BOOL DeepShare
  588. )
  589. {
  590. TCHAR lpCurDrive[4];
  591. BOOL bNoHomeDir = FALSE;
  592. BOOL bTSHomeDir = FALSE;
  593. HANDLE ImpersonationHandle = NULL;
  594. DWORD error = ERROR_SUCCESS, dwSize, dwType;
  595. HKEY hUserPolicy=NULL;
  596. DWORD dwConnectHomeDirToRoot;
  597. LONG lResult;
  598. if (GetCurrentDirectory(MAX_PATH, lpOldDir)) {
  599. lpCurDrive[0] = lpOldDir[0];
  600. lpCurDrive[1] = lpOldDir[1];
  601. lpCurDrive[2] = (TCHAR)0;
  602. }
  603. else
  604. lpCurDrive[0] = (TCHAR)0;
  605. if (!*lpHomeDir) {
  606. bNoHomeDir = TRUE;
  607. DefaultDirectory:
  608. if (!bNoHomeDir) {
  609. #if 0
  610. ReportWinlogonEvent(pGlobals,
  611. EVENTLOG_ERROR_TYPE,
  612. EVENT_SET_HOME_DIRECTORY_FAILED,
  613. sizeof(error),
  614. &error,
  615. 1,
  616. lpHomeDir);
  617. #endif
  618. }
  619. lstrcpy(lpHomeDir, lpCurDrive);
  620. if (g_IsTerminalServer) {
  621. TCHAR szProfileDir[MAX_PATH];
  622. DWORD cbufSize = MAX_PATH;
  623. if ( GetUserProfileDirectory(pGlobals->UserProcessData.UserToken, szProfileDir, &cbufSize) &&
  624. SetCurrentDirectory(szProfileDir) ) {
  625. lstrcpy(lpHomeDir, szProfileDir);
  626. bTSHomeDir = TRUE;
  627. } else {
  628. error = GetLastError();
  629. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to GetUserProfileDirectory '%ws', error = %d\n",
  630. lpHomeDir, error));
  631. lstrcpy(lpHomeDir, NULL_STRING);
  632. }
  633. }
  634. if (!bTSHomeDir) {
  635. #if 0
  636. if (SetCurrentDirectory(USERS_DEFAULT_DIRECTORY)) {
  637. lstrcat(lpHomeDir, USERS_DEFAULT_DIRECTORY);
  638. }
  639. else if (SetCurrentDirectory(USERS_DIRECTORY)) {
  640. lstrcat(lpHomeDir, USERS_DIRECTORY);
  641. }
  642. else
  643. #endif
  644. if (SetCurrentDirectory(ROOT_DIRECTORY)) {
  645. lstrcat(lpHomeDir, ROOT_DIRECTORY);
  646. }
  647. else {
  648. lstrcpy(lpHomeDir, NULL_STRING);
  649. }
  650. }
  651. if (bNoHomeDir || bTSHomeDir) {
  652. // Update the homedrive variable to reflect the correct value
  653. lstrcpy (lpHomeDrive, lpCurDrive);
  654. SetUserEnvironmentVariable(pEnv, HOMEDRIVE_VARIABLE, lpCurDrive, TRUE);
  655. *lpHomeShare = 0; // null string
  656. SetUserEnvironmentVariable(pEnv, HOMESHARE_VARIABLE, lpHomeShare, TRUE);
  657. if (*lpHomeDir) {
  658. lpHomeDir += 2;
  659. }
  660. // Update the homepath variable to reflect the correct value
  661. lstrcpy (lpHomePath, lpHomeDir);
  662. SetUserEnvironmentVariable(pEnv, HOMEPATH_VARIABLE, lpHomeDir, TRUE);
  663. }
  664. goto UpdateHomeVars;
  665. }
  666. /*
  667. * Test if homedir is a local directory.'?:\foo\bar'
  668. */
  669. if (IsUNCPath(lpHomeDir)) {
  670. NETRESOURCE NetResource;
  671. BOOL bOpenedHKCU;
  672. /*
  673. * lpHomeDir is a UNC path, use lpHomedrive.
  674. */
  675. //
  676. // First, try the (possibly) deep path:
  677. //
  678. ZeroMemory( &NetResource, sizeof( NetResource ) );
  679. NetResource.lpLocalName = lpHomeDrive;
  680. NetResource.lpRemoteName = lpHomeDir;
  681. NetResource.lpProvider = NULL;
  682. NetResource.dwType = RESOURCETYPE_DISK;
  683. dwConnectHomeDirToRoot = 0; // default
  684. bOpenedHKCU = OpenHKeyCurrentUser(pGlobals);
  685. //
  686. // Impersonate the user
  687. //
  688. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  689. if (ImpersonationHandle != NULL) {
  690. //
  691. // See the registry value to see whether we should really try to map
  692. // the whole directory or just map to the root..
  693. //
  694. if ((pGlobals->UserProcessData).hCurrentUser) {
  695. lResult = RegOpenKeyEx((pGlobals->UserProcessData).hCurrentUser, WINLOGON_POLICY_KEY, 0, KEY_READ, &hUserPolicy);
  696. if (lResult == ERROR_SUCCESS) {
  697. dwSize = sizeof(DWORD);
  698. RegQueryValueEx (hUserPolicy,
  699. TEXT("ConnectHomeDirToRoot"),
  700. NULL,
  701. &dwType,
  702. (LPBYTE) &dwConnectHomeDirToRoot,
  703. &dwSize);
  704. RegCloseKey(hUserPolicy);
  705. }
  706. }
  707. //
  708. // Revert to being 'ourself'
  709. //
  710. if (!StopImpersonating(ImpersonationHandle)) {
  711. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to revert to self"));
  712. }
  713. //
  714. // Set it to NULL
  715. //
  716. ImpersonationHandle = NULL;
  717. }
  718. else {
  719. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to impersonate user"));
  720. }
  721. if (bOpenedHKCU)
  722. CloseHKeyCurrentUser(pGlobals);
  723. if (!dwConnectHomeDirToRoot) {
  724. error = AddNetworkConnection( pGlobals, &NetResource );
  725. if (error == ERROR_SUCCESS) {
  726. //
  727. // (possibly) deep path worked!
  728. //
  729. if ( DeepShare )
  730. {
  731. //
  732. // Set homepath to just "\"
  733. //
  734. lstrcpy( lpHomePath, TEXT("\\") );
  735. // Also update the value of homeshare to reflect the correct value
  736. lstrcpy (lpHomeShare, lpHomeDir);
  737. SetUserEnvironmentVariable(pEnv, HOMESHARE_VARIABLE, lpHomeShare, TRUE);
  738. SetUserEnvironmentVariable(pEnv, HOMEPATH_VARIABLE, lpHomePath, TRUE);
  739. }
  740. }
  741. else {
  742. dwConnectHomeDirToRoot = TRUE;
  743. }
  744. }
  745. if (dwConnectHomeDirToRoot) {
  746. NetResource.lpLocalName = lpHomeDrive;
  747. NetResource.lpRemoteName = lpHomeShare;
  748. NetResource.lpProvider = NULL;
  749. NetResource.dwType = RESOURCETYPE_DISK;
  750. error = AddNetworkConnection( pGlobals, &NetResource );
  751. if ( error )
  752. {
  753. goto DefaultDirectory;
  754. }
  755. }
  756. lstrcpy(lpHomeDir, lpHomeDrive);
  757. if ( lpHomePath &&
  758. (*lpHomePath != TEXT('\\')))
  759. {
  760. lstrcat(lpHomeDir, TEXT("\\"));
  761. }
  762. lstrcat(lpHomeDir, lpHomePath);
  763. //
  764. // Impersonate the user
  765. //
  766. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  767. if (ImpersonationHandle == NULL) {
  768. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to impersonate user"));
  769. }
  770. if (!SetCurrentDirectory(lpHomeDir)) {
  771. error = GetLastError();
  772. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to SetCurrentDirectory '%ws', error = %d\n",
  773. lpHomeDir, error));
  774. //
  775. // Revert to being 'ourself'
  776. //
  777. if (ImpersonationHandle && !StopImpersonating(ImpersonationHandle)) {
  778. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to revert to self"));
  779. }
  780. goto DefaultDirectory;
  781. }
  782. }
  783. else {
  784. /*
  785. * lpHomeDir is a local path or absolute local path.
  786. */
  787. //
  788. // Impersonate the user
  789. //
  790. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  791. if (ImpersonationHandle == NULL) {
  792. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to impersonate user"));
  793. }
  794. if (!SetCurrentDirectory(lpHomeDir)) {
  795. error = GetLastError();
  796. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to SetCurrentDirectory '%ws', error = %d",
  797. lpHomeDir, error));
  798. //
  799. // Revert to being 'ourself'
  800. //
  801. if (ImpersonationHandle && !StopImpersonating(ImpersonationHandle)) {
  802. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to revert to self"));
  803. }
  804. goto DefaultDirectory;
  805. }
  806. }
  807. //
  808. // Revert to being 'ourself'
  809. //
  810. if (ImpersonationHandle && !StopImpersonating(ImpersonationHandle)) {
  811. DebugLog((DEB_ERROR, "ChangeToHomeDirectory : Failed to revert to self"));
  812. }
  813. UpdateHomeVars:
  814. //
  815. // Update the value of the home variables in the volatile environment
  816. // so that SHGetFolderPath expands these variables correctly
  817. //
  818. UpdateHomeVarsInVolatileEnv (pGlobals, lpHomeDrive, lpHomeShare, lpHomePath);
  819. return;
  820. }
  821. /***************************************************************************\
  822. * ProcessAutoexec
  823. *
  824. * History:
  825. * 01-24-92 Johannec Created.
  826. *
  827. \***************************************************************************/
  828. BOOL
  829. ProcessAutoexec(
  830. PVOID *pEnv,
  831. LPTSTR lpPathVariable
  832. )
  833. {
  834. HANDLE fh;
  835. DWORD dwFileSize;
  836. DWORD dwBytesRead;
  837. CHAR *lpBuffer = NULL;
  838. CHAR *token;
  839. CHAR Seps[] = "&\n\r"; // Seperators for tokenizing autoexec.bat
  840. BOOL Status = FALSE;
  841. TCHAR szAutoExecBat [] = TEXT("c:\\autoexec.bat");
  842. #ifdef _X86_
  843. TCHAR szTemp[3];
  844. #endif
  845. UINT uiErrMode;
  846. uiErrMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  847. #ifdef _X86_
  848. if (IsNEC_98) {
  849. if (GetEnvironmentVariable (TEXT("SystemDrive"), szTemp, 3)) {
  850. szAutoExecBat[0] = szTemp[0];
  851. }
  852. }
  853. #endif
  854. fh = CreateFile (szAutoExecBat, GENERIC_READ, FILE_SHARE_READ,
  855. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  856. SetErrorMode (uiErrMode);
  857. if (fh == INVALID_HANDLE_VALUE) {
  858. return(FALSE); //could not open autoexec.bat file, we're done.
  859. }
  860. dwFileSize = GetFileSize(fh, NULL);
  861. if (dwFileSize == -1) {
  862. goto Exit; // can't read the file size
  863. }
  864. lpBuffer = Alloc(dwFileSize+1);
  865. if (!lpBuffer) {
  866. goto Exit;
  867. }
  868. Status = ReadFile(fh, lpBuffer, dwFileSize, &dwBytesRead, NULL);
  869. if (!Status) {
  870. goto Exit; // error reading file
  871. }
  872. //
  873. // Zero terminate the buffer so we don't walk off the end
  874. //
  875. ASSERT(dwBytesRead <= dwFileSize);
  876. lpBuffer[dwBytesRead] = 0;
  877. //
  878. // Search for SET and PATH commands
  879. //
  880. token = strtok(lpBuffer, Seps);
  881. while (token != NULL) {
  882. for (;*token && *token == ' ';token++) //skip spaces
  883. ;
  884. if (*token == TEXT('@'))
  885. token++;
  886. for (;*token && *token == ' ';token++) //skip spaces
  887. ;
  888. if (!_strnicmp(token, "PATH", 4)) {
  889. STRING String;
  890. UNICODE_STRING UniString;
  891. RtlInitString(&String, (LPSTR)token);
  892. RtlAnsiStringToUnicodeString(&UniString, &String, TRUE);
  893. ProcessCommand(UniString.Buffer, pEnv);
  894. //ProcessCommand(token, pEnv);
  895. RtlFreeUnicodeString(&UniString);
  896. }
  897. if (!_strnicmp(token, "SET", 3)) {
  898. STRING String;
  899. UNICODE_STRING UniString;
  900. RtlInitString(&String, (LPSTR)token);
  901. RtlAnsiStringToUnicodeString(&UniString, &String, TRUE);
  902. ProcessSetCommand(UniString.Buffer, pEnv);
  903. //ProcessSetCommand(token, pEnv);
  904. RtlFreeUnicodeString(&UniString);
  905. }
  906. token = strtok(NULL, Seps);
  907. }
  908. Exit:
  909. CloseHandle(fh);
  910. if (lpBuffer) {
  911. Free(lpBuffer);
  912. }
  913. if (!Status) {
  914. DebugLog((DEB_ERROR, "Cannot process autoexec.bat."));
  915. }
  916. return(Status);
  917. }
  918. /***************************************************************************\
  919. * ProcessCommand
  920. *
  921. * History:
  922. * 01-24-92 Johannec Created.
  923. *
  924. \***************************************************************************/
  925. BOOL ProcessCommand(LPTSTR lpStart, PVOID *pEnv)
  926. {
  927. LPTSTR lpt, lptt;
  928. LPTSTR lpVariable;
  929. LPTSTR lpValue;
  930. LPTSTR lpExpandedValue = NULL;
  931. TCHAR c;
  932. DWORD cb, cbNeeded;
  933. //
  934. // Find environment variable.
  935. //
  936. for (lpt = lpStart; *lpt && *lpt == TEXT(' '); lpt++) //skip spaces
  937. ;
  938. if (!*lpt)
  939. return(FALSE);
  940. lptt = lpt;
  941. for (; *lpt && *lpt != TEXT(' ') && *lpt != TEXT('='); lpt++) //find end of variable name
  942. ;
  943. c = *lpt;
  944. *lpt = 0;
  945. lpVariable = Alloc(sizeof(TCHAR)*(lstrlen(lptt) + 1));
  946. if (!lpVariable)
  947. return(FALSE);
  948. lstrcpy(lpVariable, lptt);
  949. *lpt = c;
  950. //
  951. // Find environment variable value.
  952. //
  953. for (; *lpt && (*lpt == TEXT(' ') || *lpt == TEXT('=')); lpt++)
  954. ;
  955. if (!*lpt) {
  956. // if we have a blank path statement in the autoexec file,
  957. // then we don't want to pass "PATH" as the environment
  958. // variable because it trashes the system's PATH. Instead
  959. // we want to change the variable AutoexecPath. This would have
  960. // be handled below if a value had been assigned to the
  961. // environment variable.
  962. if (lstrcmpi(lpVariable, PATH_VARIABLE) == 0)
  963. {
  964. SetUserEnvironmentVariable(pEnv, AUTOEXECPATH_VARIABLE, TEXT(""), TRUE);
  965. }
  966. else
  967. {
  968. SetUserEnvironmentVariable(pEnv, lpVariable, TEXT(""), TRUE);
  969. }
  970. Free(lpVariable);
  971. return(FALSE);
  972. }
  973. lptt = lpt;
  974. for (; *lpt; lpt++) //find end of varaible value
  975. ;
  976. c = *lpt;
  977. *lpt = 0;
  978. lpValue = Alloc(sizeof(TCHAR)*(lstrlen(lptt) + 1));
  979. if (!lpValue) {
  980. Free(lpVariable);
  981. return(FALSE);
  982. }
  983. lstrcpy(lpValue, lptt);
  984. *lpt = c;
  985. #ifdef _X86_
  986. // NEC98
  987. //
  988. // If the path includes removable drive,
  989. // it is assumed that the drive assignment has changed from DOS.
  990. //
  991. if (IsNEC_98 && (lstrcmpi(lpVariable, PATH_VARIABLE) == 0) && IsPathIncludeRemovable(lpValue)) {
  992. LocalFree(lpVariable);
  993. LocalFree(lpValue);
  994. return(FALSE);
  995. }
  996. #endif
  997. cb = 1024;
  998. lpExpandedValue = Alloc(sizeof(TCHAR)*cb);
  999. if (lpExpandedValue) {
  1000. if (!lstrcmpi(lpVariable, PATH_VARIABLE)) {
  1001. lpValue = ProcessAutoexecPath(pEnv, lpValue, lstrlen(lpValue)+1);
  1002. }
  1003. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  1004. if (cbNeeded > cb) {
  1005. Free(lpExpandedValue);
  1006. cb = cbNeeded;
  1007. lpExpandedValue = Alloc(sizeof(TCHAR)*cb);
  1008. if (lpExpandedValue) {
  1009. ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  1010. }
  1011. }
  1012. }
  1013. if (!lpExpandedValue) {
  1014. lpExpandedValue = lpValue;
  1015. }
  1016. if (lstrcmpi(lpVariable, PATH_VARIABLE)) {
  1017. SetUserEnvironmentVariable(pEnv, lpVariable, lpExpandedValue, FALSE);
  1018. }
  1019. else {
  1020. SetUserEnvironmentVariable(pEnv, AUTOEXECPATH_VARIABLE, lpExpandedValue, TRUE);
  1021. }
  1022. if (lpExpandedValue != lpValue) {
  1023. Free(lpExpandedValue);
  1024. }
  1025. Free(lpVariable);
  1026. Free(lpValue);
  1027. return(TRUE);
  1028. }
  1029. /***************************************************************************\
  1030. * ProcessSetCommand
  1031. *
  1032. * History:
  1033. * 01-24-92 Johannec Created.
  1034. *
  1035. \***************************************************************************/
  1036. BOOL ProcessSetCommand(LPTSTR lpStart, PVOID *pEnv)
  1037. {
  1038. LPTSTR lpt;
  1039. //
  1040. // Find environment variable.
  1041. //
  1042. for (lpt = lpStart; *lpt && *lpt != TEXT(' '); lpt++)
  1043. ;
  1044. if (!*lpt || !_wcsnicmp(lpt,TEXT("COMSPEC"), 7))
  1045. return(FALSE);
  1046. return (ProcessCommand(lpt, pEnv));
  1047. }
  1048. /***************************************************************************\
  1049. * ProcessAutoexecPath
  1050. *
  1051. * Creates AutoexecPath environment variable using autoexec.bat
  1052. * LpValue may be freed by this routine.
  1053. *
  1054. * History:
  1055. * 06-02-92 Johannec Created.
  1056. *
  1057. \***************************************************************************/
  1058. LPTSTR ProcessAutoexecPath(PVOID *pEnv, LPTSTR lpValue, DWORD cb)
  1059. {
  1060. LPTSTR lpt;
  1061. LPTSTR lpStart;
  1062. LPTSTR lpPath;
  1063. DWORD cbt;
  1064. UNICODE_STRING Name;
  1065. UNICODE_STRING Value;
  1066. BOOL bPrevAutoexecPath;
  1067. WCHAR ch;
  1068. DWORD dwTemp, dwCount = 0;
  1069. cbt = 1024;
  1070. lpt = Alloc(sizeof(TCHAR)*cbt);
  1071. if (!lpt) {
  1072. return(lpValue);
  1073. }
  1074. *lpt = 0;
  1075. lpStart = lpValue;
  1076. RtlInitUnicodeString(&Name, AUTOEXECPATH_VARIABLE);
  1077. Value.Buffer = Alloc(sizeof(TCHAR)*cbt);
  1078. if (!Value.Buffer) {
  1079. goto Fail;
  1080. }
  1081. while (lpPath = wcsstr (lpValue, TEXT("%"))) {
  1082. if (!_wcsnicmp(lpPath+1, TEXT("PATH%"), 5)) {
  1083. //
  1084. // check if we have an autoexecpath already set, if not just remove
  1085. // the %path%
  1086. //
  1087. Value.Length = (USHORT)cbt;
  1088. Value.MaximumLength = (USHORT)cbt;
  1089. bPrevAutoexecPath = (BOOL)!RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  1090. *lpPath = 0;
  1091. dwTemp = dwCount + lstrlen (lpValue);
  1092. if (dwTemp < cbt) {
  1093. lstrcat(lpt, lpValue);
  1094. dwCount = dwTemp;
  1095. }
  1096. if (bPrevAutoexecPath) {
  1097. dwTemp = dwCount + lstrlen (Value.Buffer);
  1098. if (dwTemp < cbt) {
  1099. lstrcat(lpt, Value.Buffer);
  1100. dwCount = dwTemp;
  1101. }
  1102. }
  1103. *lpPath++ = TEXT('%');
  1104. lpPath += 5; // go passed %path%
  1105. lpValue = lpPath;
  1106. }
  1107. else {
  1108. lpPath = wcsstr(lpPath+1, TEXT("%"));
  1109. if (!lpPath) {
  1110. lpStart = NULL;
  1111. goto Fail;
  1112. }
  1113. lpPath++;
  1114. ch = *lpPath;
  1115. *lpPath = 0;
  1116. dwTemp = dwCount + lstrlen (lpValue);
  1117. if (dwTemp < cbt) {
  1118. lstrcat(lpt, lpValue);
  1119. dwCount = dwTemp;
  1120. }
  1121. *lpPath = ch;
  1122. lpValue = lpPath;
  1123. }
  1124. }
  1125. if (*lpValue) {
  1126. dwTemp = dwCount + lstrlen (lpValue);
  1127. if (dwTemp < cbt) {
  1128. lstrcat(lpt, lpValue);
  1129. dwCount = dwTemp;
  1130. }
  1131. }
  1132. Free(lpStart);
  1133. Free(Value.Buffer);
  1134. return(lpt);
  1135. Fail:
  1136. if ( Value.Buffer )
  1137. {
  1138. Free(Value.Buffer);
  1139. }
  1140. Free(lpt);
  1141. return(lpStart);
  1142. }
  1143. /***************************************************************************\
  1144. * AppendNTPathWithAutoexecPath
  1145. *
  1146. * Gets the AutoexecPath created in ProcessAutoexec, and appends it to
  1147. * the NT path.
  1148. *
  1149. * History:
  1150. * 05-28-92 Johannec Created.
  1151. *
  1152. \***************************************************************************/
  1153. BOOL
  1154. AppendNTPathWithAutoexecPath(
  1155. PVOID *pEnv,
  1156. LPTSTR lpPathVariable,
  1157. LPTSTR lpAutoexecPath
  1158. )
  1159. {
  1160. NTSTATUS Status;
  1161. UNICODE_STRING Name;
  1162. UNICODE_STRING Value;
  1163. TCHAR AutoexecPathValue[1024];
  1164. DWORD cb;
  1165. BOOL Success;
  1166. if (!*pEnv) {
  1167. return(FALSE);
  1168. }
  1169. RtlInitUnicodeString(&Name, lpAutoexecPath);
  1170. cb = 1024;
  1171. Value.Buffer = Alloc(sizeof(TCHAR)*cb);
  1172. if (!Value.Buffer) {
  1173. return(FALSE);
  1174. }
  1175. Value.Length = (USHORT)cb;
  1176. Value.MaximumLength = (USHORT)cb;
  1177. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  1178. if (!NT_SUCCESS(Status)) {
  1179. Free(Value.Buffer);
  1180. return(FALSE);
  1181. }
  1182. if (Value.Length) {
  1183. lstrcpy(AutoexecPathValue, Value.Buffer);
  1184. }
  1185. Free(Value.Buffer);
  1186. Success = BuildEnvironmentPath(pEnv, lpPathVariable, AutoexecPathValue);
  1187. RtlSetEnvironmentVariable(pEnv, &Name, NULL);
  1188. return(Success);
  1189. }
  1190. /***************************************************************************\
  1191. * AddNetworkConnection
  1192. *
  1193. * calls WNetAddConnection in the user's context.
  1194. *
  1195. * History:
  1196. * 6-26-92 Johannec Created
  1197. *
  1198. \***************************************************************************/
  1199. LONG
  1200. AddNetworkConnection(PGLOBALS pGlobals, LPNETRESOURCE lpNetResource)
  1201. {
  1202. HANDLE ImpersonationHandle;
  1203. TCHAR szMprDll[] = TEXT("mpr.dll");
  1204. CHAR szWNetAddConn[] = "WNetAddConnection2W";
  1205. CHAR szWNetCancelConn[] = "WNetCancelConnection2W";
  1206. DWORD (APIENTRY *lpfnWNetAddConn)(LPNETRESOURCE, LPTSTR, LPTSTR, DWORD);
  1207. DWORD (APIENTRY *lpfnWNetCancelConn)(LPCTSTR, DWORD, BOOL);
  1208. DWORD WNetResult;
  1209. //
  1210. // Impersonate the user
  1211. //
  1212. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  1213. if (ImpersonationHandle == NULL) {
  1214. DebugLog((DEB_ERROR, "AddNetworkConnection : Failed to impersonate user"));
  1215. return(ERROR_ACCESS_DENIED);
  1216. }
  1217. //
  1218. // Call the add connection api in the users context
  1219. //
  1220. if (!pGlobals->hMPR) {
  1221. // wasn't loaded, try to load it now.
  1222. pGlobals->hMPR = LoadLibrary(szMprDll);
  1223. }
  1224. if (pGlobals->hMPR) {
  1225. if (lpfnWNetAddConn = (DWORD (APIENTRY *)(LPNETRESOURCE, LPTSTR, LPTSTR, DWORD))
  1226. GetProcAddress(pGlobals->hMPR, (LPSTR)szWNetAddConn)) {
  1227. WNetResult = (*lpfnWNetAddConn)(lpNetResource,
  1228. NULL,
  1229. NULL,
  1230. 0);
  1231. //
  1232. // When LUID DosDevices are disabled,
  1233. // console users share the same DosDevices
  1234. // With LUID DosDevices enabled,
  1235. // users each get their own DosDevices
  1236. //
  1237. if ( (WNetResult == ERROR_ALREADY_ASSIGNED) ||
  1238. (WNetResult == ERROR_DEVICE_ALREADY_REMEMBERED) )
  1239. {
  1240. // Drive is already assigned -- undo it and retry. This is to prevent a
  1241. // user from subst-ing a drive to another user's home drive so the other
  1242. // user's home drive points somewhere inappropriate on next logon.
  1243. if (lpfnWNetCancelConn = (DWORD (APIENTRY *)(LPCTSTR, DWORD, BOOL))
  1244. GetProcAddress(pGlobals->hMPR, (LPSTR)szWNetCancelConn)) {
  1245. WNetResult = lpfnWNetCancelConn(lpNetResource->lpLocalName,
  1246. 0,
  1247. TRUE);
  1248. }
  1249. if ( (WNetResult != NO_ERROR) &&
  1250. (WNetResult == ERROR_ALREADY_ASSIGNED) &&
  1251. (GetLUIDDeviceMapsEnabled() == FALSE) )
  1252. {
  1253. // WNet didn't work -- try DefineDosDevice (as the user)
  1254. // to undo any drive substitutions that aren't background
  1255. // admin-level symlinks
  1256. DefineDosDevice(DDD_REMOVE_DEFINITION,
  1257. lpNetResource->lpLocalName,
  1258. NULL);
  1259. }
  1260. // Retry the connection
  1261. WNetResult = (*lpfnWNetAddConn)(lpNetResource,
  1262. NULL,
  1263. NULL,
  1264. 0);
  1265. }
  1266. if (WNetResult != ERROR_SUCCESS) {
  1267. DebugLog((DEB_ERROR,
  1268. "WNetAddConnection2W to %ws failed, error = %d\n",
  1269. lpNetResource->lpRemoteName,
  1270. WNetResult));
  1271. FreeLibrary(pGlobals->hMPR);
  1272. pGlobals->hMPR = NULL;
  1273. SetLastError( WNetResult );
  1274. }
  1275. if (!StopImpersonating(ImpersonationHandle)) {
  1276. DebugLog((DEB_ERROR, "AddNetworkConnection : Failed to revert to self"));
  1277. }
  1278. return( WNetResult );
  1279. } else {
  1280. DebugLog((DEB_ERROR, "Failed to get address of WNetAddConnection2W from mpr.dll"));
  1281. }
  1282. } else {
  1283. DebugLog((DEB_ERROR, "Winlogon failed to load mpr.dll for add connection"));
  1284. }
  1285. //
  1286. // Unload mpr.dll. Keeping it open messes up Novell and Banyan.
  1287. //
  1288. if ( pGlobals->hMPR ) {
  1289. FreeLibrary(pGlobals->hMPR);
  1290. pGlobals->hMPR = NULL;
  1291. }
  1292. //
  1293. // Revert to being 'ourself'
  1294. //
  1295. if (!StopImpersonating(ImpersonationHandle)) {
  1296. DebugLog((DEB_ERROR, "AddNetworkConnection : Failed to revert to self"));
  1297. }
  1298. //
  1299. // This is the failure return.
  1300. return( GetLastError() );
  1301. }
  1302. #ifdef _X86_
  1303. BOOL
  1304. IsPathIncludeRemovable(LPTSTR lpValue)
  1305. {
  1306. LPTSTR lpt, tmp;
  1307. BOOL ret = FALSE;
  1308. WCHAR c;
  1309. tmp = LocalAlloc(LPTR, (lstrlen(lpValue) + 1) * sizeof(WCHAR));
  1310. if (!tmp)
  1311. DebugLog((DEB_ERROR, "IsPathIncludeRemovable : Failed to LocalAlloc (%d)", GetLastError()));
  1312. else {
  1313. lstrcpy(tmp, lpValue);
  1314. lpt = tmp;
  1315. while (*lpt) {
  1316. // skip spaces
  1317. for ( ; *lpt && *lpt == TEXT(' '); lpt++)
  1318. ;
  1319. // check if the drive is removable
  1320. if (lpt[0] && lpt[1] && lpt[1] == TEXT(':') && lpt[2]) { // ex) "A:\"
  1321. c = lpt[3];
  1322. lpt[3] = 0;
  1323. if (GetDriveType(lpt) == DRIVE_REMOVABLE) {
  1324. lpt[3] = c;
  1325. ret = TRUE;
  1326. break;
  1327. }
  1328. lpt[3] = c;
  1329. }
  1330. // skip to the next path
  1331. for ( ; *lpt && *lpt != TEXT(';'); lpt++)
  1332. ;
  1333. if (*lpt)
  1334. lpt++;
  1335. }
  1336. LocalFree(tmp);
  1337. }
  1338. return(ret);
  1339. }
  1340. #endif
  1341. /***************************************************************************\
  1342. * GetLUIDDeviceMapsEnabled
  1343. *
  1344. * This function calls NtQueryInformationProcess() to determine if
  1345. * LUID device maps are enabled
  1346. *
  1347. * Return Value:
  1348. *
  1349. * TRUE - LUID device maps are enabled
  1350. *
  1351. * FALSE - LUID device maps are disabled
  1352. *
  1353. \***************************************************************************/
  1354. BOOL
  1355. GetLUIDDeviceMapsEnabled( VOID )
  1356. {
  1357. ULONG LUIDDeviceMapsEnabled;
  1358. NTSTATUS Status;
  1359. //
  1360. // Check if LUID Device Maps are enabled
  1361. //
  1362. Status = NtQueryInformationProcess( NtCurrentProcess(),
  1363. ProcessLUIDDeviceMapsEnabled,
  1364. &LUIDDeviceMapsEnabled,
  1365. sizeof(LUIDDeviceMapsEnabled),
  1366. NULL
  1367. );
  1368. if (!NT_SUCCESS( Status )) {
  1369. return( FALSE );
  1370. }
  1371. else {
  1372. return (LUIDDeviceMapsEnabled != 0);
  1373. }
  1374. }