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.

928 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. net.c
  5. Abstract:
  6. Network connection setting conversions
  7. Author:
  8. Jim Schmidt (jimschm) 03-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "rulehlprp.h"
  13. #include "msg.h"
  14. #include <mpr.h> // in private\inc
  15. #define DBG_NET "Net"
  16. //
  17. // Structs
  18. //
  19. typedef struct {
  20. PCTSTR User;
  21. } NETCONNFILTERARG, *PNETCONNFILTERARG;
  22. //
  23. // Import function
  24. //
  25. typedef DWORD (* I_MPRSAVECONN) (
  26. IN HKEY HiveRoot,
  27. IN PCWSTR ProviderName,
  28. IN DWORD ProviderType,
  29. IN PCWSTR UserName,
  30. IN PCWSTR LocalName,
  31. IN PCWSTR RemoteName,
  32. IN DWORD ConnectionType,
  33. IN BYTE ProviderFlags,
  34. IN DWORD DeferFlags
  35. );
  36. DWORD
  37. pMprSaveConn(
  38. IN HKEY HiveRoot,
  39. IN PCWSTR ProviderName,
  40. IN DWORD ProviderType,
  41. IN PCWSTR UserName,
  42. IN PCWSTR LocalName,
  43. IN PCWSTR RemoteName,
  44. IN DWORD ConnectionType,
  45. IN BYTE ProviderFlags,
  46. IN DWORD DeferFlags
  47. )
  48. /*++
  49. Routine Description:
  50. This routine wraps the internal routine I_MprSaveConn that is exported from
  51. mpr.dll.
  52. I_MprSaveConn was written to support the migration code. It writes the
  53. information about a connection to the network connection section of a
  54. user's registry path.
  55. NOTE: If connection information is already stored in the registry for
  56. this drive, the current information will be overwritten with the new
  57. information.
  58. Arguments:
  59. HiveRoot - A handle to the root of the user hive in which this information
  60. should be written, such as HKEY_CURRENT_USER.
  61. ProviderName - The provider that completed the connection.
  62. ProviderType - The provider type, if known. If not known, zero should
  63. be passed, and a type will not be written to the registry. (This
  64. is used by setup when upgrading from Win95 to NT.)
  65. UserName - The name of the user on whose behalf the connection was made.
  66. LocalName - The name of the local device that is redirected, with or without a
  67. trailing colon, such as "J:" or "J" or "LPT1:" or "LPT1".
  68. RemoteName - The network path to which the connection was made.
  69. ConnectionType - either RESOURCETYPE_DISK or RESOURCETYPE_PRINT.
  70. ProviderFlags - A byte of data to be saved along with the connection, and
  71. passed back to the provider when the connection is restored.
  72. DeferFlags - A DWORD to be saved in the connection's "Defer" value. If
  73. this is zero, the value is not stored.
  74. The meaning of the bits of this DWORD are as follows:
  75. DEFER_EXPLICIT_PASSWORD - a password was explicitly specified when
  76. the connection was made.
  77. DEFER_UNKNOWN - it is not known whether a password was explicitly
  78. specified when the connection was made.
  79. Return Value:
  80. ERROR_SUCCESS - If the operation was successful.
  81. Other Win32 errors - If the operation failed in any way. If a failure occurs, the
  82. information is not stored in the registry.
  83. --*/
  84. {
  85. HINSTANCE hMprInst;
  86. I_MPRSAVECONN fn;
  87. DWORD rc;
  88. hMprInst = LoadSystemLibrary (TEXT("mpr.dll"));
  89. if (!hMprInst) {
  90. LOG ((LOG_ERROR, "Cannot load mpr.dll"));
  91. return GetLastError();
  92. }
  93. fn = (I_MPRSAVECONN) GetProcAddress (hMprInst, "I_MprSaveConn"); // ANSI string!
  94. if (!fn) {
  95. LOG ((LOG_ERROR, "I_MprSaveConn is not in mpr.dll"));
  96. rc = GetLastError();
  97. } else {
  98. rc = fn (HiveRoot, ProviderName, ProviderType, UserName, LocalName,
  99. RemoteName, ConnectionType, ProviderFlags, DeferFlags);
  100. }
  101. FreeLibrary (hMprInst);
  102. return rc;
  103. }
  104. BOOL
  105. pNetConnGetValue (
  106. IN OUT PDATAOBJECT Win95ObPtr,
  107. IN PCTSTR ValueName,
  108. OUT PTSTR Buffer,
  109. IN PCTSTR LocalName // debug messages only
  110. )
  111. /*++
  112. Routine Description:
  113. This function retrieves a caller-specified value that exists in the network
  114. connection registry.
  115. Arguments:
  116. Win95ObPtr - Specifies the Win95 registry hive and key. It is updated
  117. via ReadObject.
  118. ValueName - Specifies the value to query
  119. Buffer - Receives the registry contents for the specified value name,
  120. must be at least MAX_TCHAR_PATH characters big.
  121. LocalName - Specifies the local share name (for messages only)
  122. Return Value:
  123. TRUE if successful.
  124. --*/
  125. {
  126. SetRegistryValueName (Win95ObPtr, ValueName);
  127. FreeObjectVal (Win95ObPtr);
  128. if (ReadObject (Win95ObPtr)) {
  129. MYASSERT (Win95ObPtr->ObjectType & OT_REGISTRY_TYPE);
  130. if (Win95ObPtr->Type == REG_SZ) {
  131. _tcssafecpy (Buffer, (PCTSTR) Win95ObPtr->Value.Buffer, MAX_TCHAR_PATH);
  132. if (!Buffer[0]) {
  133. DEBUGMSG ((DBG_WARNING, "NetConnFilter: %s has an empty %s value", LocalName, ValueName));
  134. }
  135. } else {
  136. DEBUGMSG ((DBG_WARNING, "NetConnFilter: %s for %s not REG_SZ", ValueName, LocalName));
  137. }
  138. } else {
  139. DEBUGMSG ((DBG_WARNING, "NetConnFilter: %s for %s cannot be read", ValueName, LocalName));
  140. }
  141. return Buffer[0] != 0;
  142. }
  143. VOID
  144. pConvertProviderName (
  145. IN OUT PTSTR Name
  146. )
  147. /*++
  148. Routine Description:
  149. This function translates Win9x provider names into WinNT equivalents. Currently
  150. the only supported provider is Microsoft Network (LANMAN).
  151. Arguments:
  152. Name - Specifies name to translate and must be big enough to receive the
  153. translated name.
  154. Return Value:
  155. TRUE if successful.
  156. --*/
  157. {
  158. INFCONTEXT ic;
  159. TCHAR NameBuf[MAX_TCHAR_PATH];
  160. //
  161. // Scan list of redirector mappings to begin using a new name
  162. //
  163. if (SetupFindFirstLine (g_WkstaMigInf, S_WKSTAMIG_REDIR_MAPPING, NULL, &ic)) {
  164. do {
  165. if (SetupGetStringField (&ic, 0, NameBuf, MAX_TCHAR_PATH, NULL)) {
  166. if (StringIMatch (Name, NameBuf)) {
  167. if (SetupGetStringField (&ic, 1, NameBuf, MAX_TCHAR_PATH, NULL)) {
  168. StringCopy (Name, NameBuf);
  169. break;
  170. }
  171. }
  172. }
  173. } while (SetupFindNextLine (&ic, &ic));
  174. }
  175. }
  176. FILTERRETURN
  177. NetConnFilter (
  178. IN CPDATAOBJECT SrcObjectPtr,
  179. IN CPDATAOBJECT DestObjectPtr,
  180. IN FILTERTYPE FilterType,
  181. IN PVOID FilterArg
  182. )
  183. /*++
  184. Routine Description:
  185. NetConnFilter is called for each registry key in the network connection settings.
  186. It converts each network connection and saves it to the NT registry.
  187. Arguments:
  188. SrcObjectPtr - Specifies Win9x registry key being enumerated (copy source)
  189. DestObjectPtr - Specifies WinNT registry key (copy destination)
  190. FilterType - Specifies the reason the filter is being called
  191. FilterArg - Caller's arg passed in to CopyObject
  192. Return Value:
  193. FILTER_RETURN_FAIL for failures
  194. FILTER_RETURN_CONTINUE to proceed to next value or key
  195. FILTER_RETURN_HANDLED to skip default registry copy
  196. --*/
  197. {
  198. PNETCONNFILTERARG ArgStruct = (PNETCONNFILTERARG) FilterArg;
  199. if (FilterType == FILTER_PROCESS_VALUES) {
  200. //
  201. // Do not process this value for local Administrator account,
  202. // logon account or Default User
  203. //
  204. if (!g_DomainUserName) {
  205. return FILTER_RETURN_HANDLED;
  206. }
  207. if (StringIMatch (g_DomainUserName, g_AdministratorStr)) {
  208. return FILTER_RETURN_HANDLED;
  209. }
  210. if (StringMatch (g_DomainUserName, S_DEFAULT_USER)) {
  211. return FILTER_RETURN_HANDLED;
  212. }
  213. //
  214. // Re-establish drive mappings (unless child key is not empty, meaning
  215. // we are in some bogus subkey).
  216. //
  217. if (SrcObjectPtr->ChildKey) {
  218. DATAOBJECT Win95Ob;
  219. PCTSTR LocalName;
  220. TCHAR ProviderName[MAX_TCHAR_PATH];
  221. TCHAR RemotePath[MAX_TCHAR_PATH];
  222. TCHAR UserName[MAX_TCHAR_PATH];
  223. PCTSTR p;
  224. DWORD rc;
  225. ZeroMemory (&Win95Ob, sizeof (Win95Ob));
  226. __try {
  227. if (!DuplicateObjectStruct (&Win95Ob, SrcObjectPtr)) {
  228. __leave; // out of memory
  229. }
  230. MYASSERT (IsWin95Object (SrcObjectPtr));
  231. MYASSERT (SrcObjectPtr->KeyPtr);
  232. MYASSERT (SrcObjectPtr->KeyPtr->KeyString);
  233. MYASSERT (SrcObjectPtr->ChildKey);
  234. //
  235. // Make LocalName point to registry key name (i.e. the drive letter)
  236. //
  237. LocalName = SrcObjectPtr->ChildKey;
  238. //
  239. // Obtain provider name
  240. //
  241. ProviderName[0] = 0;
  242. if (!pNetConnGetValue (&Win95Ob, TEXT("ProviderName"), ProviderName, LocalName)) {
  243. __leave;
  244. }
  245. //
  246. // Convert Win9x provider name to NT provider name
  247. //
  248. pConvertProviderName (ProviderName);
  249. //
  250. // Obtain remote path
  251. //
  252. RemotePath[0] = 0;
  253. if (!pNetConnGetValue (&Win95Ob, TEXT("RemotePath"), RemotePath, LocalName)) {
  254. __leave;
  255. }
  256. //
  257. // Obtain user name
  258. //
  259. StringCopy (UserName, ArgStruct->User);
  260. if (!pNetConnGetValue (&Win95Ob, TEXT("UserName"), UserName, LocalName)) {
  261. __leave;
  262. }
  263. p = _tcschr (ArgStruct->User, TEXT('\\'));
  264. if (p) {
  265. // If share user is the same as current user and there is a domain version,
  266. // use the domain version
  267. p = _tcsinc (p);
  268. if (StringIMatch (UserName, p)) {
  269. StringCopy (UserName, ArgStruct->User);
  270. }
  271. }
  272. //
  273. // Now create NT mapping
  274. //
  275. DEBUGMSG ((DBG_NET, "Adding net mapping for %s=%s", LocalName, RemotePath));
  276. rc = pMprSaveConn (g_hKeyRootNT,
  277. ProviderName,
  278. 0, // we do not know provider type
  279. UserName,
  280. LocalName,
  281. RemotePath,
  282. TcharCount (LocalName) == 1 ? RESOURCETYPE_DISK : RESOURCETYPE_PRINT,
  283. 0,
  284. DEFER_UNKNOWN // may or may not require a password
  285. );
  286. if (rc != ERROR_SUCCESS) {
  287. SetLastError (rc);
  288. LOG ((LOG_ERROR, "Failed to save %s (%s)", LocalName, RemotePath));
  289. }
  290. }
  291. __finally {
  292. FreeObjectStruct (&Win95Ob);
  293. }
  294. }
  295. ELSE_DEBUGMSG ((DBG_WARNING, "NetConnFilter: ChildKey is empty for %s",
  296. SrcObjectPtr->KeyPtr->KeyString));
  297. return FILTER_RETURN_HANDLED;
  298. } else if (FilterType == FILTER_CREATE_KEY) {
  299. return FILTER_RETURN_HANDLED;
  300. }
  301. return FILTER_RETURN_CONTINUE;
  302. }
  303. VOID
  304. pAddToPersistentList (
  305. IN PCTSTR PersistentItem,
  306. IN PCTSTR UserKeyStr // reg key off of HKR
  307. )
  308. /*++
  309. Routine Description:
  310. Creates a persistent connection entry, using the standard persistent list
  311. format. A persistent list has entries from a to z, and an order key that
  312. specifies the order of the entries. This routine finds the next available
  313. a to z entry and appends it to the order string.
  314. Arguments:
  315. PersistentItem - Specifies the value data for the a through z registry
  316. key
  317. UserKeyStr - Specifies the subkey where the persistent list is stored.
  318. It does not include HKR.
  319. Return Value:
  320. none -- errors are ignored
  321. --*/
  322. {
  323. //
  324. // Find a letter that is not used yet
  325. //
  326. HKEY PersistentConnections;
  327. TCHAR HighLetter[2];
  328. LPBYTE Data;
  329. TCHAR Order[MAX_TCHAR_PATH];
  330. LONG rc;
  331. DEBUGMSG ((DBG_NET, "Adding %s to peristent list (HKR\\%s)", PersistentItem, UserKeyStr));
  332. PersistentConnections = CreateRegKey (g_hKeyRootNT, UserKeyStr);
  333. if (!PersistentConnections) {
  334. return;
  335. }
  336. HighLetter[0] = TEXT('a');
  337. HighLetter[1] = 0;
  338. // Find unused letter
  339. do {
  340. Data = GetRegValueData (PersistentConnections, HighLetter);
  341. if (Data) {
  342. MemFree (g_hHeap, 0, Data);
  343. HighLetter[0] += 1;
  344. }
  345. } while (Data && HighLetter[0] <= TEXT('z'));
  346. if (Data) {
  347. DEBUGMSG ((DBG_VERBOSE, "pAddToPersistentList: Could not find a free letter"));
  348. return;
  349. }
  350. rc = RegSetValueEx (PersistentConnections, HighLetter, 0, REG_SZ,
  351. (LPBYTE) PersistentItem, SizeOfString (PersistentItem));
  352. SetLastError (rc);
  353. if (rc == ERROR_SUCCESS) {
  354. //
  355. // Open Order key and append HighLetter to it
  356. //
  357. Data = GetRegValueData (PersistentConnections, S_ORDER);
  358. if (Data) {
  359. StringCopy (Order, (PCTSTR) Data);
  360. MemFree (g_hHeap, 0, Data);
  361. } else {
  362. Order[0] = 0;
  363. }
  364. StringCat (Order, HighLetter);
  365. rc = RegSetValueEx (PersistentConnections, S_ORDER, 0, REG_SZ,
  366. (LPBYTE) Order, SizeOfString (Order));
  367. SetLastError (rc);
  368. if (rc != ERROR_SUCCESS) {
  369. LOG ((LOG_ERROR, "Persistent Connections: Could not set %s=%s", S_ORDER, Order));
  370. }
  371. }
  372. ELSE_DEBUGMSG ((DBG_WARNING, "pAddToPersistentList: Could not set %s=%s", HighLetter, PersistentItem));
  373. CloseRegKey (PersistentConnections);
  374. }
  375. FILTERRETURN
  376. PersistentConnFilter (
  377. IN CPDATAOBJECT SrcObjectPtr,
  378. IN CPDATAOBJECT DestObjectPtr,
  379. IN FILTERTYPE FilterType,
  380. IN PVOID FilterArg
  381. )
  382. /*++
  383. Routine Description:
  384. PersistentConnFilter is called once per persistent connection item. It converts
  385. each item into the NT format and saves the converted item to the NT registry.
  386. Arguments:
  387. SrcObjectPtr - Specifies Win9x registry key being enumerated (copy source)
  388. DestObjectPtr - Specifies WinNT registry key (copy destination)
  389. FilterType - Specifies the reason the filter is being called
  390. FilterArg - Caller's arg passed in to CopyObject
  391. Return Value:
  392. FILTER_RETURN_FAIL for failures
  393. FILTER_RETURN_HANDLED to skip all sub keys, values, etc.
  394. --*/
  395. {
  396. if (FilterType == FILTER_KEY_ENUM && SrcObjectPtr->ChildKey) {
  397. //
  398. // Do not process this value for local Administrator account
  399. //
  400. if (g_DomainUserName && StringIMatch (g_DomainUserName, g_AdministratorStr)) {
  401. return FILTER_RETURN_HANDLED;
  402. }
  403. //
  404. // The Win95 code stores connections as
  405. // ././computer./share..name (dot is used for escaping)
  406. //
  407. // NT stores connections as \\computer\share and does not
  408. // need things like provider, user name or whatever nonsense
  409. // Win95 is storing.
  410. //
  411. if (SrcObjectPtr->ChildKey &&
  412. SrcObjectPtr->ChildKey[0] == TEXT('.') &&
  413. SrcObjectPtr->ChildKey[1] == TEXT('/') &&
  414. TcharCount (SrcObjectPtr->ChildKey) < 64
  415. ) {
  416. TCHAR TranslatedShareName[MAX_TCHAR_PATH];
  417. PCTSTR p;
  418. PTSTR Dest;
  419. p = SrcObjectPtr->ChildKey;
  420. Dest = TranslatedShareName;
  421. while (*p) {
  422. if (_tcsnextc (p) == TEXT('.')) {
  423. p = _tcsinc (p);
  424. if (!(*p)) {
  425. break;
  426. }
  427. }
  428. if (_tcsnextc (p) == TEXT('/')) {
  429. *Dest = TEXT('\\');
  430. } else {
  431. _copytchar (Dest, p);
  432. }
  433. Dest = _tcsinc (Dest);
  434. p = _tcsinc (p);
  435. }
  436. *Dest = 0;
  437. if (Dest) {
  438. pAddToPersistentList (TranslatedShareName, S_PERSISTENT_CONNECTIONS);
  439. }
  440. }
  441. }
  442. return FILTER_RETURN_HANDLED;
  443. }
  444. BOOL
  445. RuleHlpr_CreateNetMappings (
  446. IN PCTSTR SrcObjectStr,
  447. IN PCTSTR DestObjectStr,
  448. IN PCTSTR User,
  449. IN PVOID Data
  450. )
  451. /*++
  452. Routine Description:
  453. This function is an enumerated rule helper callback that copies network mappings.
  454. It is called for each network mapping using the key enumeration in rulehlpr.c.
  455. Arguments:
  456. SrcObjectStr - Specifies Win9x registry key being enumerated (copy source)
  457. DestObjectStr - Specifies WinNT registry key (copy destination)
  458. User - Specifies the current user name (or NULL for default)
  459. Data - Specifies caller-supplied data (see table in rulehlpr.c)
  460. Return Value:
  461. Tri-state:
  462. TRUE to continue enumeration
  463. FALSE and last error != ERROR_SUCCESS if an error occurred
  464. FALSE and last error == ERROR_SUCCESS to stop enumeration silently
  465. --*/
  466. {
  467. DATAOBJECT PersistentRegOb;
  468. DATAOBJECT DestOb;
  469. NETCONNFILTERARG ArgStruct;
  470. BOOL b = FALSE;
  471. // If Administrator, default user or local machine, ignore this rule
  472. if (!User || (!User[0]) || StringIMatch (User, g_AdministratorStr)) {
  473. SetLastError (ERROR_SUCCESS);
  474. return FALSE;
  475. }
  476. //
  477. // We need to enumerate all keys in SrcObjectStr. For each key,
  478. // create a drive mapping.
  479. //
  480. __try {
  481. ZeroMemory (&PersistentRegOb, sizeof (DATAOBJECT));
  482. ZeroMemory (&DestOb, sizeof (DATAOBJECT));
  483. if (!CreateObjectStruct (SrcObjectStr, &PersistentRegOb, WIN95OBJECT)) {
  484. DEBUGMSG ((DBG_WARNING, "CreateNetMappings: %s is invalid", SrcObjectStr));
  485. __leave;
  486. }
  487. if (!(PersistentRegOb.ObjectType & OT_TREE)) {
  488. DEBUGMSG ((DBG_WARNING, "CreateNetMappings: %s does not specify subkeys -- skipping rule", SrcObjectStr));
  489. b = TRUE;
  490. __leave;
  491. }
  492. DuplicateObjectStruct (&DestOb, &PersistentRegOb);
  493. SetPlatformType (&DestOb, WINNTOBJECT);
  494. ArgStruct.User = User;
  495. b = (FILTER_RETURN_FAIL != CopyObject (&PersistentRegOb, &DestOb, NetConnFilter, &ArgStruct));
  496. // If there were no mappings, return success
  497. if (!b) {
  498. if (GetLastError() == ERROR_FILE_NOT_FOUND ||
  499. GetLastError() == ERROR_NO_MORE_ITEMS
  500. ) {
  501. b = TRUE;
  502. }
  503. }
  504. }
  505. __finally {
  506. FreeObjectStruct (&DestOb);
  507. FreeObjectStruct (&PersistentRegOb);
  508. }
  509. return b;
  510. }
  511. BOOL
  512. RuleHlpr_ConvertRecentMappings (
  513. IN PCTSTR SrcObjectStr,
  514. IN PCTSTR DestObjectStr,
  515. IN PCTSTR User,
  516. IN PVOID Data
  517. )
  518. /*++
  519. Routine Description:
  520. This function is an enumerated rule helper callback that copies recent network
  521. mappings. It is called for each network mapping using the key enumeration in
  522. rulehlpr.c.
  523. Arguments:
  524. SrcObjectStr - Specifies Win9x registry key being enumerated (copy source)
  525. DestObjectStr - Specifies WinNT registry key (copy destination)
  526. User - Specifies the current user name (or NULL for default)
  527. Data - Specifies caller-supplied data (see table in rulehlpr.c)
  528. Return Value:
  529. Tri-state:
  530. TRUE to continue enumeration
  531. FALSE and last error != ERROR_SUCCESS if an error occurred
  532. FALSE and last error == ERROR_SUCCESS to stop enumeration silently
  533. --*/
  534. {
  535. DATAOBJECT PersistentRegOb;
  536. DATAOBJECT DestOb;
  537. BOOL b = FALSE;
  538. // If Administrator, default user or local machine, ignore this rule
  539. if (!User || (!User[0]) || StringIMatch (User, g_AdministratorStr)) {
  540. SetLastError (ERROR_SUCCESS);
  541. return FALSE;
  542. }
  543. //
  544. // We need to enumerate all keys in SrcObjectStr. For each key,
  545. // create a drive mapping.
  546. //
  547. __try {
  548. ZeroMemory (&PersistentRegOb, sizeof (DATAOBJECT));
  549. ZeroMemory (&DestOb, sizeof (DATAOBJECT));
  550. if (!CreateObjectStruct (SrcObjectStr, &PersistentRegOb, WIN95OBJECT)) {
  551. DEBUGMSG ((DBG_WARNING, "PersistentConnections: %s is invalid", SrcObjectStr));
  552. __leave;
  553. }
  554. if (!(PersistentRegOb.ObjectType & OT_TREE)) {
  555. DEBUGMSG ((DBG_WARNING, "PersistentConnections: %s does not specify subkeys -- skipping rule", SrcObjectStr));
  556. b = TRUE;
  557. __leave;
  558. }
  559. DuplicateObjectStruct (&DestOb, &PersistentRegOb);
  560. SetPlatformType (&DestOb, WINNTOBJECT);
  561. b = CopyObject (&PersistentRegOb, &DestOb, PersistentConnFilter, NULL);
  562. // If CopyObject completed, or there were no mappings, return success
  563. if (!b) {
  564. if (GetLastError() == ERROR_FILE_NOT_FOUND ||
  565. GetLastError() == ERROR_NO_MORE_ITEMS
  566. ) {
  567. b = TRUE;
  568. }
  569. }
  570. }
  571. __finally {
  572. FreeObjectStruct (&DestOb);
  573. FreeObjectStruct (&PersistentRegOb);
  574. }
  575. return b;
  576. }
  577. BOOL
  578. pWasAccountMigrated (
  579. IN PCTSTR UserName
  580. )
  581. /*++
  582. Routine Description:
  583. pWasAccountMigrated queries the UserDatLoc category to determine if the
  584. specified user was scheduled migration. If they are listed in UserDatLoc,
  585. then they will be migrated.
  586. Arguments:
  587. UserName - Specifies user to look up. Must be fixed version.
  588. Return Value:
  589. TRUE if the user was migrated, FALSE if not.
  590. --*/
  591. {
  592. MEMDB_ENUM e;
  593. return MemDbEnumFields (&e, MEMDB_CATEGORY_USER_DAT_LOC, UserName);
  594. }
  595. BOOL
  596. ValFn_VerifyLastLoggedOnUser (
  597. IN OUT PDATAOBJECT ObPtr
  598. )
  599. /*++
  600. Routine Description:
  601. This routine uses the RuleHlpr_ConvertRegVal simplification routine. See
  602. rulehlpr.c for details. The simplification routine does almost all the work
  603. for us; all we need to do is update the value.
  604. ValFn_VerifyLastLoggedOnUser is used to validate the user being copied
  605. into the default logon user setting. If the user account was not migrated,
  606. then "Administrator" is used as the default logon user.
  607. Arguments:
  608. ObPtr - Specifies the Win95 data object as specified in wkstamig.inf,
  609. [Win9x Data Conversion] section. The object value is then modified.
  610. After returning, the merge code then copies the data to the NT
  611. destination, which has a new location (specified in wkstamig.inf,
  612. [Map Win9x to WinNT] section).
  613. Return Value:
  614. Tri-state:
  615. TRUE to allow merge code to continue processing (it writes the value)
  616. FALSE and last error == ERROR_SUCCESS to continue, but skip the write
  617. FALSE and last error != ERROR_SUCCESS if an error occurred
  618. --*/
  619. {
  620. PCTSTR UserName;
  621. PCTSTR AdministratorAcct;
  622. BOOL ForceAdministrator;
  623. TCHAR FixedUserName[MAX_USER_NAME];
  624. //
  625. // Verify user was migrated. If not, change value to Administrator.
  626. //
  627. UserName = (PCTSTR) ObPtr->Value.Buffer;
  628. if (SizeOfString (UserName) > ObPtr->Value.Size) {
  629. DEBUGMSG ((DBG_WHOOPS, "User Name string not nul-terminated"));
  630. ForceAdministrator = TRUE;
  631. FixedUserName[0] = 0;
  632. } else {
  633. _tcssafecpy (FixedUserName, UserName, MAX_USER_NAME);
  634. GetFixedUserName (FixedUserName);
  635. if (pWasAccountMigrated (FixedUserName)) {
  636. ForceAdministrator = FALSE;
  637. } else {
  638. ForceAdministrator = TRUE;
  639. }
  640. }
  641. if (ForceAdministrator) {
  642. AdministratorAcct = GetStringResource (MSG_ADMINISTRATOR_ACCOUNT);
  643. __try {
  644. if (!ReplaceValue (
  645. ObPtr,
  646. (PBYTE) AdministratorAcct,
  647. SizeOfString (AdministratorAcct)
  648. )) {
  649. #pragma prefast(suppress:242, "Don't care about perf of try/finally here")
  650. return FALSE;
  651. }
  652. }
  653. __finally {
  654. FreeStringResource (AdministratorAcct);
  655. }
  656. } else {
  657. if (!StringMatch (UserName, FixedUserName)) {
  658. if (!ReplaceValue (
  659. ObPtr,
  660. (PBYTE) FixedUserName,
  661. SizeOfString (FixedUserName)
  662. )) {
  663. return FALSE;
  664. }
  665. }
  666. }
  667. return TRUE;
  668. }