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.

1476 lines
48 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. win31io.c
  5. Abstract:
  6. This file contains Win 3.1 Inter-Operability functions.
  7. Author:
  8. Steve Wood (stevewo) 21-Feb-1993
  9. Revision History:
  10. --*/
  11. #include "advapi.h"
  12. #include <stdio.h>
  13. #include <winbasep.h>
  14. #include "win31io.h"
  15. #define EVENTLOG_SOURCE "Windows 3.1 Migration"
  16. BOOL
  17. WaitForEventLogToStart( VOID );
  18. #define SIZE_OF_TOKEN_INFORMATION \
  19. sizeof( TOKEN_USER ) \
  20. + sizeof( SID ) \
  21. + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
  22. typedef struct _WIN31IO_STATE {
  23. HANDLE EventLog;
  24. HANDLE SoftwareRoot;
  25. HANDLE UserRoot;
  26. HANDLE Win31IOKey;
  27. BOOL QueryOnly;
  28. PWSTR WindowsPath;
  29. PWSTR FileNamePart;
  30. PWSTR WorkBuffer;
  31. ULONG cchWorkBuffer;
  32. PWIN31IO_STATUS_CALLBACK StatusCallback;
  33. PVOID CallbackParameter;
  34. WCHAR szWindowsDirectory[ MAX_PATH ];
  35. PSID UserSid;
  36. UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ];
  37. WCHAR QueryBuffer[ 64 ];
  38. } WIN31IO_STATE, *PWIN31IO_STATE;
  39. HANDLE
  40. OpenCreateKey(
  41. IN HANDLE Root,
  42. IN PWSTR Path,
  43. IN BOOL WriteAccess
  44. );
  45. BOOL
  46. SnapShotWin31IniFilesToRegistry(
  47. IN OUT PWIN31IO_STATE State
  48. );
  49. BOOL
  50. SnapShotWin31GroupsToRegistry(
  51. IN OUT PWIN31IO_STATE State
  52. );
  53. BOOL
  54. SnapShotWin31RegDatToRegistry(
  55. IN OUT PWIN31IO_STATE State
  56. );
  57. BOOL
  58. InitializeWin31State(
  59. IN WIN31IO_EVENT EventType,
  60. OUT PWIN31IO_STATE State
  61. );
  62. VOID
  63. TerminateWin31State(
  64. IN WIN31IO_EVENT EventType,
  65. IN OUT PWIN31IO_STATE State
  66. );
  67. BOOL
  68. InitializeWin31State(
  69. IN WIN31IO_EVENT EventType,
  70. OUT PWIN31IO_STATE State
  71. )
  72. {
  73. NTSTATUS Status;
  74. ULONG cch;
  75. HANDLE TokenHandle;
  76. ULONG ReturnLength;
  77. memset( State, 0, sizeof( *State ) );
  78. cch = GetWindowsDirectoryW( State->szWindowsDirectory,
  79. sizeof( State->szWindowsDirectory ) / sizeof (WCHAR)
  80. );
  81. State->WindowsPath = State->szWindowsDirectory;
  82. State->FileNamePart = State->WindowsPath + cch;
  83. *State->FileNamePart++ = OBJ_NAME_PATH_SEPARATOR;
  84. if (EventType == Win31SystemStartEvent) {
  85. State->SoftwareRoot = OpenCreateKey( NULL,
  86. L"\\Registry\\Machine\\Software",
  87. FALSE
  88. );
  89. if (State->SoftwareRoot == NULL) {
  90. return FALSE;
  91. }
  92. }
  93. else {
  94. Status = RtlOpenCurrentUser( GENERIC_READ, &State->UserRoot );
  95. if (!NT_SUCCESS( Status )) {
  96. BaseSetLastNTError( Status );
  97. return FALSE;
  98. }
  99. if (OpenThreadToken( GetCurrentThread(),
  100. TOKEN_READ,
  101. TRUE,
  102. &TokenHandle
  103. ) ||
  104. OpenProcessToken( GetCurrentProcess(),
  105. TOKEN_READ,
  106. &TokenHandle
  107. )
  108. ) {
  109. if (GetTokenInformation( TokenHandle,
  110. TokenUser,
  111. &State->TokenInformation,
  112. sizeof( State->TokenInformation ),
  113. &ReturnLength
  114. )
  115. ) {
  116. PTOKEN_USER UserToken = (PTOKEN_USER)&State->TokenInformation;
  117. State->UserSid = UserToken->User.Sid;
  118. }
  119. CloseHandle( TokenHandle );
  120. }
  121. }
  122. State->Win31IOKey = OpenCreateKey( EventType == Win31SystemStartEvent ?
  123. State->SoftwareRoot : State->UserRoot,
  124. L"Windows 3.1 Migration Status",
  125. TRUE
  126. );
  127. if (State->Win31IOKey == NULL) {
  128. if (State->SoftwareRoot != NULL) {
  129. NtClose( State->SoftwareRoot );
  130. }
  131. if (State->UserRoot != NULL) {
  132. NtClose( State->UserRoot );
  133. }
  134. if (State->EventLog != NULL) {
  135. DeregisterEventSource( State->EventLog );
  136. }
  137. return FALSE;
  138. }
  139. else {
  140. return TRUE;
  141. }
  142. return TRUE;
  143. }
  144. VOID
  145. TerminateWin31State(
  146. IN WIN31IO_EVENT EventType,
  147. IN OUT PWIN31IO_STATE State
  148. )
  149. {
  150. if (State->Win31IOKey != NULL) {
  151. NtClose( State->Win31IOKey );
  152. }
  153. if (State->SoftwareRoot != NULL) {
  154. NtClose( State->SoftwareRoot );
  155. }
  156. if (State->UserRoot != NULL) {
  157. NtClose( State->UserRoot );
  158. }
  159. if (State->EventLog != NULL && State->EventLog != INVALID_HANDLE_VALUE) {
  160. DeregisterEventSource( State->EventLog );
  161. }
  162. return;
  163. }
  164. #define MAX_EVENT_STRINGS 8
  165. VOID
  166. ReportWin31IOEvent(
  167. IN PWIN31IO_STATE State,
  168. IN WORD EventType,
  169. IN DWORD EventId,
  170. IN DWORD SizeOfRawData,
  171. IN PVOID RawData,
  172. IN DWORD NumberOfStrings,
  173. ...
  174. )
  175. {
  176. va_list arglist;
  177. ULONG i;
  178. PWSTR Strings[ MAX_EVENT_STRINGS ];
  179. va_start( arglist, NumberOfStrings );
  180. if (NumberOfStrings > MAX_EVENT_STRINGS) {
  181. NumberOfStrings = MAX_EVENT_STRINGS;
  182. }
  183. for (i=0; i<NumberOfStrings; i++) {
  184. Strings[ i ] = va_arg( arglist, PWSTR );
  185. }
  186. if (State->EventLog == NULL) {
  187. State->EventLog = RegisterEventSource( NULL, EVENTLOG_SOURCE );
  188. if (State->EventLog == NULL) {
  189. if (WaitForEventLogToStart()) {
  190. State->EventLog = RegisterEventSource( NULL, EVENTLOG_SOURCE );
  191. }
  192. if (State->EventLog == NULL) {
  193. KdPrint(( "WIN31IO: RegisterEventSource( %s ) failed - %u\n", EVENTLOG_SOURCE, GetLastError() ));
  194. State->EventLog = INVALID_HANDLE_VALUE;
  195. return;
  196. }
  197. }
  198. }
  199. if (State->EventLog != INVALID_HANDLE_VALUE) {
  200. if (!ReportEventW( State->EventLog,
  201. EventType,
  202. 0, // event category
  203. EventId,
  204. State->UserSid,
  205. (WORD)NumberOfStrings,
  206. SizeOfRawData,
  207. Strings,
  208. RawData
  209. )
  210. ) {
  211. KdPrint(( "WIN31IO: ReportEvent( %u ) failed - %u\n", EventId, GetLastError() ));
  212. }
  213. }
  214. }
  215. int
  216. Win31IOExceptionHandler(
  217. IN DWORD ExceptionCode,
  218. IN PEXCEPTION_POINTERS ExceptionInfo,
  219. IN OUT PWIN31IO_STATE State
  220. );
  221. int
  222. Win31IOExceptionHandler(
  223. IN DWORD ExceptionCode,
  224. IN PEXCEPTION_POINTERS ExceptionInfo,
  225. IN OUT PWIN31IO_STATE State
  226. )
  227. {
  228. KdPrint(( "WIN31IO: Unexpected exception %08x at %08x referencing %08x\n",
  229. ExceptionInfo->ExceptionRecord->ExceptionCode,
  230. ExceptionInfo->ExceptionRecord->ExceptionAddress,
  231. ExceptionInfo->ExceptionRecord->ExceptionInformation[ 1 ]
  232. ));
  233. //
  234. // Unexpected exception. Log the event with the exception record
  235. // so we can figure it out later.
  236. //
  237. ReportWin31IOEvent( State,
  238. EVENTLOG_ERROR_TYPE,
  239. WIN31IO_EVENT_EXCEPTION,
  240. sizeof( *(ExceptionInfo->ExceptionRecord) ),
  241. ExceptionInfo->ExceptionRecord,
  242. 0
  243. );
  244. return EXCEPTION_EXECUTE_HANDLER;
  245. }
  246. DWORD
  247. WINAPI
  248. QueryWindows31FilesMigration(
  249. IN WIN31IO_EVENT EventType
  250. )
  251. {
  252. DWORD Flags;
  253. WIN31IO_STATE State;
  254. if (EventType == Win31LogoffEvent) {
  255. return 0;
  256. }
  257. if (!InitializeWin31State( EventType, &State )) {
  258. return 0;
  259. }
  260. State.QueryOnly = TRUE;
  261. State.WorkBuffer = State.QueryBuffer;
  262. State.cchWorkBuffer = sizeof( State.QueryBuffer ) / sizeof( WCHAR );
  263. Flags = 0;
  264. try {
  265. try {
  266. if (EventType == Win31SystemStartEvent) {
  267. if (SnapShotWin31IniFilesToRegistry( &State )) {
  268. Flags |= WIN31_MIGRATE_INIFILES;
  269. }
  270. if (SnapShotWin31RegDatToRegistry( &State )) {
  271. Flags |= WIN31_MIGRATE_REGDAT;
  272. }
  273. }
  274. else {
  275. if (SnapShotWin31IniFilesToRegistry( &State )) {
  276. Flags |= WIN31_MIGRATE_INIFILES;
  277. }
  278. if (SnapShotWin31GroupsToRegistry( &State )) {
  279. Flags |= WIN31_MIGRATE_GROUPS;
  280. }
  281. }
  282. }
  283. except( Win31IOExceptionHandler( GetExceptionCode(),
  284. GetExceptionInformation(),
  285. &State
  286. )
  287. ) {
  288. BaseSetLastNTError( GetExceptionCode() );
  289. }
  290. }
  291. finally {
  292. TerminateWin31State( EventType, &State );
  293. }
  294. return Flags;
  295. }
  296. BOOL
  297. WINAPI
  298. SynchronizeWindows31FilesAndWindowsNTRegistry(
  299. IN WIN31IO_EVENT EventType,
  300. IN DWORD Flags,
  301. IN PWIN31IO_STATUS_CALLBACK StatusCallback,
  302. IN PVOID CallbackParameter
  303. )
  304. {
  305. BOOL Result;
  306. VIRTUAL_BUFFER Buffer;
  307. ULONG cch;
  308. WIN31IO_STATE State;
  309. if (Flags == 0 || EventType == Win31LogoffEvent) {
  310. return TRUE;
  311. }
  312. if (!InitializeWin31State( EventType, &State )) {
  313. return TRUE;
  314. }
  315. State.QueryOnly = FALSE;
  316. State.StatusCallback = StatusCallback;
  317. State.CallbackParameter = CallbackParameter;
  318. Result = FALSE;
  319. try {
  320. try {
  321. try {
  322. cch = ((64 * 1024) / sizeof( WCHAR )) - 1;
  323. if (!CreateVirtualBuffer( &Buffer, cch * sizeof( WCHAR ), cch * sizeof( WCHAR ) )) {
  324. leave;
  325. }
  326. State.WorkBuffer = Buffer.Base;
  327. State.cchWorkBuffer = cch;
  328. Result = TRUE;
  329. if (EventType == Win31SystemStartEvent) {
  330. if (Flags & WIN31_MIGRATE_INIFILES) {
  331. Result &= SnapShotWin31IniFilesToRegistry( &State );
  332. }
  333. if (Flags & WIN31_MIGRATE_REGDAT) {
  334. Result &= SnapShotWin31RegDatToRegistry( &State );
  335. }
  336. }
  337. else {
  338. if (Flags & WIN31_MIGRATE_INIFILES) {
  339. Result &= SnapShotWin31IniFilesToRegistry( &State );
  340. }
  341. if (Flags & WIN31_MIGRATE_GROUPS) {
  342. Result &= SnapShotWin31GroupsToRegistry( &State );
  343. }
  344. }
  345. }
  346. except( VirtualBufferExceptionHandler( GetExceptionCode(),
  347. GetExceptionInformation(),
  348. &Buffer
  349. )
  350. ) {
  351. if (GetExceptionCode() == STATUS_ACCESS_VIOLATION) {
  352. BaseSetLastNTError( STATUS_NO_MEMORY );
  353. }
  354. else {
  355. BaseSetLastNTError( GetExceptionCode() );
  356. }
  357. Result = FALSE;
  358. }
  359. }
  360. except( Win31IOExceptionHandler( GetExceptionCode(),
  361. GetExceptionInformation(),
  362. &State
  363. )
  364. ) {
  365. BaseSetLastNTError( GetExceptionCode() );
  366. Result = FALSE;
  367. }
  368. }
  369. finally {
  370. TerminateWin31State( EventType, &State );
  371. FreeVirtualBuffer( &Buffer );
  372. }
  373. return Result;
  374. }
  375. BOOL
  376. SnapShotWin31IniFileKey(
  377. IN OUT PWIN31IO_STATE State,
  378. IN PWSTR TempFileName,
  379. IN PWSTR FileName,
  380. IN PWSTR ApplicationName,
  381. IN PWSTR KeyName
  382. );
  383. BOOL
  384. SnapShotWin31IniFileSection(
  385. IN OUT PWIN31IO_STATE State,
  386. IN PWSTR TempFileName,
  387. IN PWSTR FileName,
  388. IN PWSTR ApplicationName
  389. );
  390. BOOL
  391. SnapShotWin31IniFileSections(
  392. IN OUT PWIN31IO_STATE State,
  393. IN PWSTR TempFileName,
  394. IN PWSTR FileName
  395. );
  396. BOOL
  397. SnapShotWin31IniFilesToRegistry(
  398. IN OUT PWIN31IO_STATE State
  399. )
  400. {
  401. BOOL Result;
  402. PWSTR s, s1, FileName, ApplicationName, KeyName;
  403. ULONG n;
  404. PWSTR CurrentFileName;
  405. WCHAR Win31IniFileName[ MAX_PATH ];
  406. WCHAR TempIniFileName[ MAX_PATH ];
  407. HANDLE FindHandle;
  408. WIN32_FIND_DATAW FindFileData;
  409. HANDLE MigrationKey, Key;
  410. ULONG cchBufferUsed;
  411. MigrationKey = OpenCreateKey( State->Win31IOKey, L"IniFiles", !State->QueryOnly );
  412. if (State->QueryOnly) {
  413. if (MigrationKey != NULL) {
  414. NtClose( MigrationKey );
  415. return FALSE;
  416. }
  417. }
  418. else {
  419. if (MigrationKey == NULL) {
  420. return FALSE;
  421. }
  422. }
  423. Result = FALSE;
  424. wcscpy( State->FileNamePart, L"system.ini" );
  425. FindHandle = FindFirstFileW( State->WindowsPath, &FindFileData );
  426. if (FindHandle != INVALID_HANDLE_VALUE) {
  427. FindClose( FindHandle );
  428. if (FindFileData.nFileSizeLow > 1024) {
  429. Result = TRUE;
  430. }
  431. }
  432. if (!Result || State->QueryOnly) {
  433. if (MigrationKey == NULL) {
  434. MigrationKey = OpenCreateKey( State->Win31IOKey, L"IniFiles", TRUE );
  435. }
  436. if (MigrationKey != NULL) {
  437. NtClose( MigrationKey );
  438. }
  439. return Result;
  440. }
  441. cchBufferUsed = 0;
  442. if (State->UserRoot != NULL) {
  443. Result = QueryWin31IniFilesMappedToRegistry( WIN31_INIFILES_MAPPED_TO_USER,
  444. State->WorkBuffer,
  445. State->cchWorkBuffer,
  446. &cchBufferUsed
  447. );
  448. }
  449. else {
  450. Result = QueryWin31IniFilesMappedToRegistry( WIN31_INIFILES_MAPPED_TO_SYSTEM,
  451. State->WorkBuffer,
  452. State->cchWorkBuffer,
  453. &cchBufferUsed
  454. );
  455. }
  456. if (Result) {
  457. s = State->WorkBuffer;
  458. State->WorkBuffer += cchBufferUsed;
  459. State->cchWorkBuffer -= cchBufferUsed;
  460. CurrentFileName = NULL;
  461. TempIniFileName[ 0 ] = UNICODE_NULL;
  462. do {
  463. FileName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
  464. while (*s++) {
  465. ;
  466. }
  467. ApplicationName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
  468. while (*s++) {
  469. ;
  470. }
  471. KeyName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
  472. while (*s++) {
  473. ;
  474. }
  475. if (FileName) {
  476. if (!CurrentFileName || _wcsicmp( FileName, CurrentFileName )) {
  477. if (TempIniFileName[ 0 ] != UNICODE_NULL) {
  478. WritePrivateProfileStringW( NULL, NULL, NULL, L"" );
  479. if (!DeleteFileW( TempIniFileName )) {
  480. KdPrint(( "WIN31IO: DeleteFile( %ws ) - failed (%u)\n",
  481. TempIniFileName,
  482. GetLastError()
  483. ));
  484. }
  485. TempIniFileName[ 0 ] = UNICODE_NULL;
  486. }
  487. CurrentFileName = NULL;
  488. GetWindowsDirectoryW( Win31IniFileName, sizeof( Win31IniFileName ) / sizeof (WCHAR) );
  489. wcscat( Win31IniFileName, L"\\" );
  490. wcscat( Win31IniFileName, FileName );
  491. wcscpy( TempIniFileName, Win31IniFileName );
  492. _wcslwr( TempIniFileName );
  493. s1 = wcsstr( TempIniFileName, L".ini" );
  494. if (!s1) {
  495. s1 = wcschr( TempIniFileName, UNICODE_NULL );
  496. if (s1[-1] == L'.') {
  497. s1--;
  498. }
  499. }
  500. n = 0;
  501. while (n < 1000) {
  502. swprintf( s1, L".%03u", n++ );
  503. if (CopyFileW( Win31IniFileName, TempIniFileName, TRUE )) {
  504. if (State->StatusCallback != NULL) {
  505. (State->StatusCallback)( FileName, State->CallbackParameter );
  506. }
  507. Key = OpenCreateKey( MigrationKey, FileName, TRUE );
  508. if (Key != NULL) {
  509. NtClose( Key );
  510. }
  511. CurrentFileName = FileName;
  512. break;
  513. }
  514. else
  515. if (GetLastError() != ERROR_FILE_EXISTS) {
  516. if (GetLastError() != ERROR_FILE_NOT_FOUND) {
  517. KdPrint(("WIN31IO: CopyFile( %ws, %ws ) failed - %u\n",
  518. Win31IniFileName,
  519. TempIniFileName,
  520. GetLastError()
  521. ));
  522. }
  523. break;
  524. }
  525. }
  526. if (CurrentFileName == NULL) {
  527. TempIniFileName[ 0 ] = UNICODE_NULL;
  528. CurrentFileName = FileName;
  529. }
  530. }
  531. if (TempIniFileName[ 0 ] != UNICODE_NULL) {
  532. if (ApplicationName) {
  533. if (KeyName) {
  534. if (SnapShotWin31IniFileKey( State,
  535. TempIniFileName,
  536. FileName,
  537. ApplicationName,
  538. KeyName
  539. )
  540. ) {
  541. ReportWin31IOEvent( State,
  542. EVENTLOG_INFORMATION_TYPE,
  543. WIN31IO_EVENT_MIGRATE_INI_VARIABLE,
  544. 0,
  545. NULL,
  546. 3,
  547. KeyName,
  548. ApplicationName,
  549. FileName
  550. );
  551. }
  552. else {
  553. ReportWin31IOEvent( State,
  554. EVENTLOG_WARNING_TYPE,
  555. WIN31IO_EVENT_MIGRATE_INI_VARIABLE_FAILED,
  556. 0,
  557. NULL,
  558. 3,
  559. KeyName,
  560. ApplicationName,
  561. FileName
  562. );
  563. }
  564. }
  565. else {
  566. if (SnapShotWin31IniFileSection( State,
  567. TempIniFileName,
  568. FileName,
  569. ApplicationName
  570. )
  571. ) {
  572. ReportWin31IOEvent( State,
  573. EVENTLOG_INFORMATION_TYPE,
  574. WIN31IO_EVENT_MIGRATE_INI_SECTION,
  575. 0,
  576. NULL,
  577. 2,
  578. ApplicationName,
  579. FileName
  580. );
  581. }
  582. else {
  583. ReportWin31IOEvent( State,
  584. EVENTLOG_WARNING_TYPE,
  585. WIN31IO_EVENT_MIGRATE_INI_SECTION_FAILED,
  586. 0,
  587. NULL,
  588. 2,
  589. ApplicationName,
  590. FileName
  591. );
  592. }
  593. }
  594. }
  595. else {
  596. if (SnapShotWin31IniFileSections( State,
  597. TempIniFileName,
  598. FileName
  599. )
  600. ) {
  601. ReportWin31IOEvent( State,
  602. EVENTLOG_INFORMATION_TYPE,
  603. WIN31IO_EVENT_MIGRATE_INI_FILE,
  604. 0,
  605. NULL,
  606. 1,
  607. FileName
  608. );
  609. }
  610. else {
  611. ReportWin31IOEvent( State,
  612. EVENTLOG_WARNING_TYPE,
  613. WIN31IO_EVENT_MIGRATE_INI_FILE_FAILED,
  614. 0,
  615. NULL,
  616. 1,
  617. FileName
  618. );
  619. }
  620. }
  621. }
  622. }
  623. }
  624. while (*s != UNICODE_NULL);
  625. State->WorkBuffer -= cchBufferUsed;
  626. State->cchWorkBuffer += cchBufferUsed;
  627. }
  628. if (TempIniFileName[ 0 ] != UNICODE_NULL) {
  629. WritePrivateProfileStringW( NULL, NULL, NULL, L"" );
  630. if (!DeleteFileW( TempIniFileName )) {
  631. KdPrint(( "WIN31IO: DeleteFile( %ws ) - failed (%u)\n",
  632. TempIniFileName,
  633. GetLastError()
  634. ));
  635. }
  636. }
  637. if (MigrationKey != NULL) {
  638. NtClose( MigrationKey );
  639. }
  640. return Result;
  641. }
  642. BOOL
  643. SnapShotWin31IniFileKey(
  644. IN OUT PWIN31IO_STATE State,
  645. IN PWSTR TempFileName,
  646. IN PWSTR FileName,
  647. IN PWSTR ApplicationName,
  648. IN PWSTR KeyName
  649. )
  650. {
  651. ULONG cch;
  652. cch = GetPrivateProfileStringW( ApplicationName,
  653. KeyName,
  654. NULL,
  655. State->WorkBuffer,
  656. State->cchWorkBuffer,
  657. TempFileName
  658. );
  659. if (cch != 0) {
  660. if (WritePrivateProfileStringW( ApplicationName,
  661. KeyName,
  662. State->WorkBuffer,
  663. FileName
  664. )
  665. ) {
  666. return TRUE;
  667. }
  668. else {
  669. KdPrint(( "WIN31IO: Copy to %ws [%ws].%ws == %ws (failed - %u)\n", FileName, ApplicationName, KeyName, State->WorkBuffer, GetLastError() ));
  670. return FALSE;
  671. }
  672. }
  673. else {
  674. return TRUE;
  675. }
  676. }
  677. BOOL
  678. SnapShotWin31IniFileSection(
  679. IN OUT PWIN31IO_STATE State,
  680. IN PWSTR TempFileName,
  681. IN PWSTR FileName,
  682. IN PWSTR ApplicationName
  683. )
  684. {
  685. BOOL Result;
  686. PWSTR KeyName;
  687. ULONG cch;
  688. Result = TRUE;
  689. cch = GetPrivateProfileStringW( ApplicationName,
  690. NULL,
  691. NULL,
  692. State->WorkBuffer,
  693. State->cchWorkBuffer,
  694. TempFileName
  695. );
  696. if (cch != 0) {
  697. KeyName = State->WorkBuffer;
  698. cch += 1; // Account for extra null
  699. State->WorkBuffer += cch;
  700. State->cchWorkBuffer -= cch;
  701. while (*KeyName != UNICODE_NULL) {
  702. Result &= SnapShotWin31IniFileKey( State,
  703. TempFileName,
  704. FileName,
  705. ApplicationName,
  706. KeyName
  707. );
  708. while (*KeyName++) {
  709. ;
  710. }
  711. }
  712. State->WorkBuffer -= cch;
  713. State->cchWorkBuffer += cch;
  714. }
  715. return Result;
  716. }
  717. BOOL
  718. SnapShotWin31IniFileSections(
  719. IN OUT PWIN31IO_STATE State,
  720. IN PWSTR TempFileName,
  721. IN PWSTR FileName
  722. )
  723. {
  724. BOOL Result;
  725. PWSTR ApplicationName;
  726. ULONG cch;
  727. Result = TRUE;
  728. cch = GetPrivateProfileStringW( NULL,
  729. NULL,
  730. NULL,
  731. State->WorkBuffer,
  732. State->cchWorkBuffer,
  733. TempFileName
  734. );
  735. if (cch != 0) {
  736. ApplicationName = State->WorkBuffer;
  737. cch += 1; // Account for extra null
  738. State->WorkBuffer += cch;
  739. State->cchWorkBuffer -= cch;
  740. while (*ApplicationName != UNICODE_NULL) {
  741. Result &= SnapShotWin31IniFileSection( State,
  742. TempFileName,
  743. FileName,
  744. ApplicationName
  745. );
  746. while (*ApplicationName++) {
  747. ;
  748. }
  749. }
  750. State->WorkBuffer -= cch;
  751. State->cchWorkBuffer += cch;
  752. }
  753. return Result;
  754. }
  755. BOOL
  756. ConvertWindows31GroupsToRegistry(
  757. IN OUT PWIN31IO_STATE State,
  758. IN HANDLE MigrationKey,
  759. IN HANDLE CommonGroupsKey,
  760. IN HANDLE PersonalGroupsKey,
  761. IN PWSTR IniFileName,
  762. IN PWSTR GroupNames,
  763. IN ULONG nGroupNames
  764. );
  765. BOOL
  766. SnapShotWin31GroupsToRegistry(
  767. IN OUT PWIN31IO_STATE State
  768. )
  769. {
  770. BOOL Result;
  771. PWSTR GroupNames, s;
  772. DWORD nGroupNames, cchGroupNames;
  773. HANDLE MigrationKey, PersonalGroupsKey, CommonGroupsKey;
  774. MigrationKey = OpenCreateKey( State->Win31IOKey, L"Groups", !State->QueryOnly );
  775. if (State->QueryOnly) {
  776. if (MigrationKey != NULL) {
  777. NtClose( MigrationKey );
  778. return FALSE;
  779. }
  780. }
  781. else {
  782. if (MigrationKey == NULL) {
  783. return FALSE;
  784. }
  785. }
  786. Result = FALSE;
  787. wcscpy( State->FileNamePart, L"progman.ini" );
  788. if (GetFileAttributesW( State->WindowsPath ) != 0xFFFFFFFF) {
  789. cchGroupNames = GetPrivateProfileStringW( L"Groups",
  790. NULL,
  791. L"",
  792. State->WorkBuffer,
  793. State->cchWorkBuffer,
  794. State->WindowsPath
  795. );
  796. if (cchGroupNames != 0) {
  797. Result = TRUE;
  798. }
  799. }
  800. if (!Result || State->QueryOnly) {
  801. if (MigrationKey == NULL) {
  802. MigrationKey = OpenCreateKey( State->Win31IOKey, L"Groups", TRUE );
  803. }
  804. if (MigrationKey != NULL) {
  805. NtClose( MigrationKey );
  806. }
  807. return Result;
  808. }
  809. if (cchGroupNames) {
  810. PersonalGroupsKey = OpenCreateKey( State->UserRoot,
  811. L"UNICODE Program Groups",
  812. !State->QueryOnly
  813. );
  814. if (PersonalGroupsKey == NULL) {
  815. if (MigrationKey != NULL) {
  816. NtClose( MigrationKey );
  817. }
  818. return FALSE;
  819. }
  820. CommonGroupsKey = OpenCreateKey( NULL,
  821. L"\\Registry\\Machine\\Software\\Program Groups",
  822. FALSE
  823. );
  824. GroupNames = s = State->WorkBuffer;
  825. nGroupNames = 0;
  826. while (*s) {
  827. while (*s++) {
  828. ;
  829. }
  830. nGroupNames += 1;
  831. }
  832. State->WorkBuffer = s + 1;
  833. State->cchWorkBuffer -= cchGroupNames + 1;
  834. ConvertWindows31GroupsToRegistry( State,
  835. MigrationKey,
  836. CommonGroupsKey,
  837. PersonalGroupsKey,
  838. State->WindowsPath,
  839. GroupNames,
  840. nGroupNames
  841. );
  842. State->WorkBuffer = GroupNames,
  843. State->cchWorkBuffer += cchGroupNames + 1;
  844. NtClose( PersonalGroupsKey );
  845. if (CommonGroupsKey != NULL) {
  846. NtClose( CommonGroupsKey );
  847. }
  848. }
  849. if (MigrationKey != NULL) {
  850. NtClose( MigrationKey );
  851. }
  852. return TRUE;
  853. }
  854. BOOL
  855. ConvertWindows31GroupsToRegistry(
  856. IN OUT PWIN31IO_STATE State,
  857. IN HANDLE MigrationKey,
  858. IN HANDLE CommonGroupsKey,
  859. IN HANDLE PersonalGroupsKey,
  860. IN PWSTR IniFileName,
  861. IN PWSTR GroupNames,
  862. IN ULONG nGroupNames
  863. )
  864. {
  865. BOOL Result;
  866. NTSTATUS Status;
  867. PGROUP_DEF16 Group16;
  868. PGROUP_DEF Group32;
  869. UNICODE_STRING Group32Name;
  870. PWSTR Group16PathName;
  871. PWSTR Group16FileName;
  872. PWSTR s;
  873. ANSI_STRING AnsiString;
  874. ULONG NumberOfPersonalGroupNames;
  875. ULONG OldNumberOfPersonalGroupNames;
  876. HANDLE GroupNamesKey, SettingsKey, Key;
  877. NumberOfPersonalGroupNames = QueryNumberOfPersonalGroupNames( State->UserRoot,
  878. &GroupNamesKey,
  879. &SettingsKey
  880. );
  881. OldNumberOfPersonalGroupNames = NumberOfPersonalGroupNames;
  882. Result = TRUE;
  883. while (*GroupNames) {
  884. //
  885. // Get the group file (.grp) name
  886. //
  887. if (GetPrivateProfileStringW( L"Groups",
  888. GroupNames,
  889. L"",
  890. State->WorkBuffer,
  891. State->cchWorkBuffer,
  892. IniFileName
  893. )
  894. ) {
  895. Group16PathName = State->WorkBuffer;
  896. Group16 = LoadGroup16( Group16PathName );
  897. if (Group16 != NULL) {
  898. Group16FileName = Group16PathName + wcslen( Group16PathName );
  899. while (Group16FileName > Group16PathName) {
  900. if (Group16FileName[ -1 ] == OBJ_NAME_PATH_SEPARATOR) {
  901. break;
  902. }
  903. Group16FileName -= 1;
  904. }
  905. //
  906. // Get the group name.
  907. //
  908. if (Group16->pName == 0) {
  909. RtlInitUnicodeString( &Group32Name, Group16FileName );
  910. Status = STATUS_SUCCESS;
  911. }
  912. else {
  913. RtlInitAnsiString( &AnsiString, (PSZ)PTR( Group16, Group16->pName ) );
  914. Status = RtlAnsiStringToUnicodeString( &Group32Name, &AnsiString, TRUE );
  915. s = Group32Name.Buffer;
  916. while (*s) {
  917. if (*s == OBJ_NAME_PATH_SEPARATOR) {
  918. *s = L'/';
  919. }
  920. s += 1;
  921. }
  922. }
  923. if (NT_SUCCESS( Status )) {
  924. if (DoesExistGroup( PersonalGroupsKey, Group32Name.Buffer )) {
  925. ReportWin31IOEvent( State,
  926. EVENTLOG_INFORMATION_TYPE,
  927. WIN31IO_EVENT_MIGRATE_GROUP_EXISTS,
  928. 0,
  929. NULL,
  930. 2,
  931. Group16PathName,
  932. Group32Name.Buffer
  933. );
  934. }
  935. else
  936. if (DoesExistGroup( CommonGroupsKey, Group32Name.Buffer )) {
  937. ReportWin31IOEvent( State,
  938. EVENTLOG_INFORMATION_TYPE,
  939. WIN31IO_EVENT_MIGRATE_GROUP_EXISTS,
  940. 0,
  941. NULL,
  942. 2,
  943. Group16PathName,
  944. Group32Name.Buffer
  945. );
  946. }
  947. else {
  948. // DumpGroup16( State->WorkBuffer, Group16 );
  949. Group32 = CreateGroupFromGroup16( AnsiString.Buffer, Group16 );
  950. if (Group32 != NULL) {
  951. if (Group32 == (PGROUP_DEF)-1) {
  952. ReportWin31IOEvent( State,
  953. EVENTLOG_WARNING_TYPE,
  954. WIN31IO_EVENT_MIGRATE_GROUP_FAILED4,
  955. 0,
  956. NULL,
  957. 1,
  958. Group32Name.Buffer
  959. );
  960. Group32 = NULL;
  961. }
  962. else {
  963. // DumpGroup( Group32Name.Buffer, Group32 );
  964. if (!SaveGroup( PersonalGroupsKey,
  965. Group32Name.Buffer,
  966. Group32
  967. )
  968. ) {
  969. ReportWin31IOEvent( State,
  970. EVENTLOG_WARNING_TYPE,
  971. WIN31IO_EVENT_MIGRATE_GROUP_FAILED,
  972. 0,
  973. NULL,
  974. 1,
  975. Group32Name.Buffer
  976. );
  977. }
  978. else
  979. if (!NewPersonalGroupName( GroupNamesKey,
  980. Group32Name.Buffer,
  981. NumberOfPersonalGroupNames+1
  982. )
  983. ) {
  984. DeleteGroup( PersonalGroupsKey, Group32Name.Buffer );
  985. ReportWin31IOEvent( State,
  986. EVENTLOG_WARNING_TYPE,
  987. WIN31IO_EVENT_MIGRATE_GROUP_FAILED,
  988. 0,
  989. NULL,
  990. 1,
  991. Group32Name.Buffer
  992. );
  993. }
  994. else {
  995. if (State->StatusCallback != NULL) {
  996. (State->StatusCallback)( Group16FileName, State->CallbackParameter );
  997. }
  998. ReportWin31IOEvent( State,
  999. EVENTLOG_INFORMATION_TYPE,
  1000. WIN31IO_EVENT_MIGRATE_GROUP,
  1001. 0,
  1002. NULL,
  1003. 1,
  1004. Group32Name.Buffer
  1005. );
  1006. NumberOfPersonalGroupNames += 1;
  1007. Key = OpenCreateKey( MigrationKey, Group16FileName, TRUE );
  1008. if (Key != NULL) {
  1009. NtClose( Key );
  1010. }
  1011. else {
  1012. KdPrint(("WIN31IO: (3)Unable to create sub migration key for %ws (%u)\n", State->WorkBuffer, GetLastError() ));
  1013. }
  1014. }
  1015. UnloadGroup( Group32 );
  1016. }
  1017. }
  1018. else {
  1019. WCHAR ErrorCode[ 32 ];
  1020. _snwprintf( ErrorCode,
  1021. sizeof( ErrorCode ) / sizeof( WCHAR ),
  1022. L"%u",
  1023. GetLastError()
  1024. );
  1025. ReportWin31IOEvent( State,
  1026. EVENTLOG_WARNING_TYPE,
  1027. WIN31IO_EVENT_MIGRATE_GROUP_FAILED1,
  1028. 0,
  1029. NULL,
  1030. 2,
  1031. State->WorkBuffer,
  1032. ErrorCode
  1033. );
  1034. }
  1035. }
  1036. RtlFreeUnicodeString( &Group32Name );
  1037. }
  1038. UnloadGroup16( Group16 );
  1039. }
  1040. else {
  1041. WCHAR ErrorCode[ 32 ];
  1042. _snwprintf( ErrorCode,
  1043. sizeof( ErrorCode ) / sizeof( WCHAR ),
  1044. L"%u",
  1045. GetLastError()
  1046. );
  1047. ReportWin31IOEvent( State,
  1048. EVENTLOG_WARNING_TYPE,
  1049. WIN31IO_EVENT_MIGRATE_GROUP_FAILED1,
  1050. 0,
  1051. NULL,
  1052. 2,
  1053. State->WorkBuffer,
  1054. ErrorCode
  1055. );
  1056. }
  1057. }
  1058. else {
  1059. ReportWin31IOEvent( State,
  1060. EVENTLOG_WARNING_TYPE,
  1061. WIN31IO_EVENT_MIGRATE_GROUP_FAILED2,
  1062. 0,
  1063. NULL,
  1064. 2,
  1065. IniFileName,
  1066. GroupNames
  1067. );
  1068. }
  1069. while (*GroupNames++) {
  1070. ;
  1071. }
  1072. }
  1073. if (OldNumberOfPersonalGroupNames != NumberOfPersonalGroupNames) {
  1074. UNICODE_STRING ValueName;
  1075. ULONG ValueData = TRUE;
  1076. RtlInitUnicodeString( &ValueName, L"InitialArrange" );
  1077. Status = NtSetValueKey( SettingsKey,
  1078. &ValueName,
  1079. 0,
  1080. REG_DWORD,
  1081. &ValueData,
  1082. sizeof( ValueData )
  1083. );
  1084. #if DBG
  1085. if (!NT_SUCCESS( Status )) {
  1086. KdPrint(( "WIN31IO: Unable to set value of %wZ - Status == %x\n", &ValueName, Status ));
  1087. }
  1088. #endif
  1089. }
  1090. NtClose( SettingsKey );
  1091. NtClose( GroupNamesKey );
  1092. return Result;
  1093. }
  1094. BOOL
  1095. SnapShotWin31RegDatToRegistry(
  1096. IN OUT PWIN31IO_STATE State
  1097. )
  1098. {
  1099. BOOL Result;
  1100. HANDLE MigrationKey;
  1101. PREG_HEADER16 RegDat16;
  1102. MigrationKey = OpenCreateKey( State->Win31IOKey, L"REG.DAT", !State->QueryOnly );
  1103. if (State->QueryOnly) {
  1104. if (MigrationKey != NULL) {
  1105. NtClose( MigrationKey );
  1106. return FALSE;
  1107. }
  1108. }
  1109. else {
  1110. if (MigrationKey == NULL) {
  1111. return FALSE;
  1112. }
  1113. }
  1114. Result = FALSE;
  1115. wcscpy( State->FileNamePart, L"reg.dat" );
  1116. if (GetFileAttributesW( State->WindowsPath ) != 0xFFFFFFFF) {
  1117. Result = TRUE;
  1118. }
  1119. if (!Result || State->QueryOnly) {
  1120. if (MigrationKey == NULL) {
  1121. MigrationKey = OpenCreateKey( State->Win31IOKey, L"REG.DAT", TRUE );
  1122. }
  1123. if (MigrationKey != NULL) {
  1124. NtClose( MigrationKey );
  1125. }
  1126. return Result;
  1127. }
  1128. RegDat16 = LoadRegistry16( State->WindowsPath );
  1129. if (RegDat16 != NULL) {
  1130. if (State->StatusCallback != NULL) {
  1131. (State->StatusCallback)( State->WindowsPath, State->CallbackParameter );
  1132. }
  1133. if (CreateRegistryClassesFromRegistry16( State->SoftwareRoot, RegDat16 )) {
  1134. ReportWin31IOEvent( State,
  1135. EVENTLOG_INFORMATION_TYPE,
  1136. WIN31IO_EVENT_MIGRATE_REGDAT,
  1137. 0,
  1138. NULL,
  1139. 1,
  1140. State->WindowsPath
  1141. );
  1142. }
  1143. else {
  1144. ReportWin31IOEvent( State,
  1145. EVENTLOG_WARNING_TYPE,
  1146. WIN31IO_EVENT_MIGRATE_REGDAT_FAILED,
  1147. 0,
  1148. NULL,
  1149. 1,
  1150. State->WindowsPath
  1151. );
  1152. }
  1153. UnloadRegistry16( RegDat16 );
  1154. }
  1155. if (MigrationKey != NULL) {
  1156. NtClose( MigrationKey );
  1157. }
  1158. return TRUE;
  1159. }
  1160. #define SERVICE_TO_WAIT_FOR "EventLog"
  1161. #define MAX_TICKS_WAIT 90000 // ms
  1162. BOOL
  1163. WaitForEventLogToStart( VOID )
  1164. {
  1165. BOOL bStarted = FALSE;
  1166. DWORD StartTickCount;
  1167. DWORD dwOldCheckPoint = (DWORD)-1;
  1168. SC_HANDLE hScManager = NULL;
  1169. SC_HANDLE hService = NULL;
  1170. SERVICE_STATUS ServiceStatus;
  1171. if ((hScManager = OpenSCManager( NULL,
  1172. NULL,
  1173. SC_MANAGER_CONNECT
  1174. )
  1175. ) == (SC_HANDLE) NULL
  1176. ) {
  1177. KdPrint(("WIN31IO: IsNetworkStarted: OpenSCManager failed, error = %d\n", GetLastError()));
  1178. goto Exit;
  1179. }
  1180. //
  1181. // OpenService
  1182. //
  1183. if ((hService = OpenService( hScManager,
  1184. SERVICE_TO_WAIT_FOR,
  1185. SERVICE_QUERY_STATUS
  1186. )
  1187. ) == (SC_HANDLE) NULL
  1188. ) {
  1189. KdPrint(("WIN31IO: IsNetworkStarted: OpenService failed, error = %d\n", GetLastError()));
  1190. goto Exit;
  1191. }
  1192. //
  1193. // Loop until the service starts or we think it never will start
  1194. // or we've exceeded our maximum time delay.
  1195. //
  1196. StartTickCount = GetTickCount();
  1197. while (!bStarted) {
  1198. if ((GetTickCount() - StartTickCount) > MAX_TICKS_WAIT) {
  1199. KdPrint(("WIN31IO: Max wait exceeded waiting for service <%s> to start\n", SERVICE_TO_WAIT_FOR));
  1200. break;
  1201. }
  1202. if (!QueryServiceStatus( hService, &ServiceStatus )) {
  1203. KdPrint(("WIN31IO: IsNetworkStarted: QueryServiceStatus failed, error = %d\n", GetLastError()));
  1204. break;
  1205. }
  1206. if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) {
  1207. KdPrint(("WIN31IO: Service STOPPED"));
  1208. if (ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) {
  1209. KdPrint(("WIN31IO: Waiting for 3 secs"));
  1210. Sleep(3000);
  1211. }
  1212. else {
  1213. KdPrint(("WIN31IO: Service exit code = %d, returning failure\n", ServiceStatus.dwWin32ExitCode));
  1214. break;
  1215. }
  1216. }
  1217. else
  1218. if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
  1219. (ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
  1220. (ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) ||
  1221. (ServiceStatus.dwCurrentState == SERVICE_PAUSED)
  1222. ) {
  1223. bStarted = TRUE;
  1224. }
  1225. else
  1226. if (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) {
  1227. //
  1228. // Wait to give a chance for the network to start.
  1229. //
  1230. Sleep( ServiceStatus.dwWaitHint );
  1231. }
  1232. else {
  1233. KdPrint(( "WIN31IO: Service in unknown state : %d\n", ServiceStatus.dwCurrentState ));
  1234. }
  1235. }
  1236. Exit:
  1237. if (hScManager != NULL) {
  1238. CloseServiceHandle( hScManager );
  1239. }
  1240. if (hService != NULL) {
  1241. CloseServiceHandle( hService );
  1242. }
  1243. return( bStarted );
  1244. }
  1245. HANDLE
  1246. OpenCreateKey(
  1247. IN HANDLE Root,
  1248. IN PWSTR Path,
  1249. IN BOOL WriteAccess
  1250. )
  1251. {
  1252. NTSTATUS Status;
  1253. HANDLE Key;
  1254. UNICODE_STRING KeyName;
  1255. OBJECT_ATTRIBUTES ObjectAttributes;
  1256. ULONG CreateDisposition;
  1257. RtlInitUnicodeString( &KeyName, Path );
  1258. InitializeObjectAttributes( &ObjectAttributes,
  1259. &KeyName,
  1260. OBJ_CASE_INSENSITIVE,
  1261. Root,
  1262. NULL
  1263. );
  1264. Status = NtOpenKey( &Key,
  1265. WriteAccess ? (STANDARD_RIGHTS_WRITE |
  1266. KEY_QUERY_VALUE |
  1267. KEY_ENUMERATE_SUB_KEYS |
  1268. KEY_SET_VALUE |
  1269. KEY_CREATE_SUB_KEY
  1270. )
  1271. : GENERIC_READ,
  1272. &ObjectAttributes
  1273. );
  1274. if (NT_SUCCESS( Status )) {
  1275. return Key;
  1276. }
  1277. else
  1278. if (!WriteAccess) {
  1279. BaseSetLastNTError( Status );
  1280. return NULL;
  1281. }
  1282. Status = NtCreateKey( &Key,
  1283. STANDARD_RIGHTS_WRITE |
  1284. KEY_QUERY_VALUE |
  1285. KEY_ENUMERATE_SUB_KEYS |
  1286. KEY_SET_VALUE |
  1287. KEY_CREATE_SUB_KEY,
  1288. &ObjectAttributes,
  1289. 0,
  1290. NULL,
  1291. 0,
  1292. &CreateDisposition
  1293. );
  1294. if (!NT_SUCCESS( Status )) {
  1295. BaseSetLastNTError( Status );
  1296. return NULL;
  1297. }
  1298. else {
  1299. return Key;
  1300. }
  1301. }