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.

998 lines
25 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Implements code common to two or more apps.
  7. Author:
  8. Jim Schmidt (jimschm) 17-Oct-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "ism.h"
  17. #include "modules.h"
  18. #include "trans.h"
  19. #include "common.h"
  20. //
  21. // Strings
  22. //
  23. // none
  24. //
  25. // Constants
  26. //
  27. #define LOG_VERBOSE_BIT 0x01
  28. #define LOG_UNUSED_BIT 0x02 // for v1 compatibility, do not use
  29. #define LOG_STATUS_BIT 0x04
  30. #define LOG_DEBUGGER_BIT 0x08
  31. #define LOG_UPDATE_BIT 0x10
  32. //
  33. // Macros
  34. //
  35. // none
  36. //
  37. // Types
  38. //
  39. // none
  40. //
  41. // Globals
  42. //
  43. // none
  44. //
  45. // Macro expansion list
  46. //
  47. #define REQUIRED_INFS \
  48. DEFMAC(OSFILES, TEXT("USMTDef.inf")) \
  49. //
  50. // Private function prototypes
  51. //
  52. // none
  53. //
  54. // Macro expansion definition
  55. //
  56. // this is the structure used for handling required infs
  57. typedef struct {
  58. PCTSTR InfId;
  59. PCTSTR InfName;
  60. } REQUIREDINF_STRUCT, *PREQUIREDINF_STRUCT;
  61. // declare a global array of required infs
  62. #define DEFMAC(infid,infname) {TEXT(#infid),infname},
  63. static REQUIREDINF_STRUCT g_RequiredInfs[] = {
  64. REQUIRED_INFS
  65. {NULL, NULL}
  66. };
  67. #undef DEFMAC
  68. //
  69. // Code
  70. //
  71. VOID
  72. InitAppCommon (
  73. VOID
  74. )
  75. {
  76. InfGlobalInit (FALSE);
  77. RegInitialize();
  78. }
  79. VOID
  80. TerminateAppCommon (
  81. VOID
  82. )
  83. {
  84. RegTerminate();
  85. InfGlobalInit (FALSE);
  86. }
  87. HINF
  88. InitRequiredInfs (
  89. IN PCTSTR AppPath,
  90. IN PCSTR FailMsgId
  91. )
  92. {
  93. PCTSTR fullPath;
  94. HINF result = INVALID_HANDLE_VALUE;
  95. PREQUIREDINF_STRUCT p = g_RequiredInfs;
  96. while (p->InfId) {
  97. fullPath = JoinPaths (AppPath, p->InfName);
  98. if (DoesFileExist (fullPath)) {
  99. if (result == INVALID_HANDLE_VALUE) {
  100. result = SetupOpenInfFile (fullPath, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
  101. if (result == INVALID_HANDLE_VALUE) {
  102. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  103. }
  104. } else {
  105. if (!SetupOpenAppendInfFile (fullPath, result, NULL)) {
  106. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  107. }
  108. }
  109. } else {
  110. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  111. }
  112. FreePathString (fullPath);
  113. p++;
  114. }
  115. return result;
  116. }
  117. VOID
  118. PrintMsgOnConsole (
  119. IN UINT MsgId
  120. )
  121. {
  122. PCTSTR msg;
  123. #ifdef UNICODE
  124. PCSTR ansimsg;
  125. #endif
  126. msg = GetStringResource (MsgId);
  127. if (msg) {
  128. #ifdef UNICODE
  129. ansimsg = ConvertWtoA (msg);
  130. printf ("%s", ansimsg);
  131. FreeConvertedStr (ansimsg);
  132. #else
  133. printf ("%s", msg);
  134. #endif
  135. FreeStringResource (msg);
  136. }
  137. }
  138. VOID
  139. UploadEnvVars (
  140. IN MIG_PLATFORMTYPEID Platform
  141. )
  142. {
  143. PCTSTR envVars = NULL;
  144. MULTISZ_ENUM e;
  145. PTSTR envString;
  146. PTSTR p;
  147. //
  148. // we are going to write here all defined environment variables
  149. //
  150. envVars = (PCTSTR) GetEnvironmentStrings();
  151. if (envVars) {
  152. if (EnumFirstMultiSz (&e, envVars)) {
  153. do {
  154. envString = DuplicatePathString (e.CurrentString, 0);
  155. p = _tcschr (envString, TEXT('='));
  156. //
  157. // Get rid of empty environment strings or the dummy env string starting
  158. // with '='
  159. //
  160. if (!p || p == envString) {
  161. FreePathString (envString);
  162. continue;
  163. }
  164. *p = 0;
  165. p = _tcsinc (p);
  166. if (p) {
  167. IsmSetEnvironmentString (Platform, S_SYSENVVAR_GROUP, envString, p);
  168. }
  169. FreePathString (envString);
  170. } while (EnumNextMultiSz (&e));
  171. }
  172. }
  173. }
  174. VOID
  175. SetLogVerbosity (
  176. IN INT VerboseLevel
  177. )
  178. {
  179. LOG_LEVEL logBitmap = 0;
  180. if (VerboseLevel < 0) {
  181. VerboseLevel = 0;
  182. }
  183. // Always ON
  184. logBitmap = LL_FATAL_ERROR | LL_MODULE_ERROR | LL_ERROR;
  185. // ON for VERBOSE_BIT
  186. if (VerboseLevel & LOG_VERBOSE_BIT) {
  187. logBitmap |= LL_WARNING | LL_INFORMATION;
  188. }
  189. // ON for STATUS_BIT
  190. if (VerboseLevel & LOG_STATUS_BIT) {
  191. logBitmap |= LL_STATUS;
  192. }
  193. // ON for UPDATE_BIT
  194. if (VerboseLevel & LOG_UPDATE_BIT) {
  195. logBitmap |= LL_UPDATE;
  196. }
  197. #ifdef PRERELEASE
  198. LogSetVerboseBitmap (
  199. logBitmap,
  200. LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION|LL_STATUS|LL_UPDATE,
  201. VerboseLevel & LOG_DEBUGGER_BIT
  202. );
  203. #else
  204. LogSetVerboseBitmap (
  205. logBitmap,
  206. LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION,
  207. VerboseLevel & LOG_DEBUGGER_BIT
  208. );
  209. #endif
  210. }
  211. BOOL
  212. GetFilePath (
  213. IN PCTSTR UserSpecifiedFile,
  214. OUT PTSTR Buffer,
  215. IN UINT BufferTchars
  216. )
  217. {
  218. PTSTR tempBuffer = NULL;
  219. TCHAR infDir[MAX_MBCHAR_PATH];
  220. TCHAR modulePath[MAX_MBCHAR_PATH];
  221. TCHAR currentDir[MAX_MBCHAR_PATH];
  222. PTSTR p;
  223. PCTSTR userFile = NULL;
  224. PTSTR dontCare;
  225. __try {
  226. //
  227. // Locate the file using the full path specified by the user, or
  228. // if only a file spec was given, use the following priorities:
  229. //
  230. // 1. Current directory
  231. // 2. Directory where the tool is
  232. // 3. INF directory
  233. //
  234. // In all cases, return the full path to the file.
  235. //
  236. if (Buffer) {
  237. *Buffer = 0;
  238. } else {
  239. __leave;
  240. }
  241. tempBuffer = AllocText (BufferTchars);
  242. *tempBuffer = 0;
  243. if (!_tcsrchr (UserSpecifiedFile, TEXT('\\'))) {
  244. //
  245. // Compute INF directory, module directory and current directory
  246. //
  247. if (!GetWindowsDirectory (infDir, ARRAYSIZE(infDir) - 5)) {
  248. MYASSERT (FALSE);
  249. __leave;
  250. }
  251. StringCat (infDir, TEXT("\\inf"));
  252. if (!GetModuleFileName (NULL, modulePath, ARRAYSIZE(modulePath))) {
  253. MYASSERT (FALSE);
  254. __leave;
  255. }
  256. p = _tcsrchr (modulePath, TEXT('\\'));
  257. if (p) {
  258. *p = 0;
  259. } else {
  260. MYASSERT (FALSE);
  261. __leave;
  262. }
  263. if (!GetCurrentDirectory (ARRAYSIZE(currentDir), currentDir)) {
  264. MYASSERT (FALSE);
  265. __leave;
  266. }
  267. //
  268. // Let's see if it's in the current dir
  269. //
  270. userFile = JoinPaths (currentDir, UserSpecifiedFile);
  271. if (DoesFileExist (userFile)) {
  272. GetFullPathName (
  273. userFile,
  274. BufferTchars,
  275. tempBuffer,
  276. &dontCare
  277. );
  278. } else {
  279. //
  280. // Let's try the module dir
  281. //
  282. FreePathString (userFile);
  283. userFile = JoinPaths (modulePath, UserSpecifiedFile);
  284. if (DoesFileExist (userFile)) {
  285. GetFullPathName (
  286. userFile,
  287. BufferTchars,
  288. tempBuffer,
  289. &dontCare
  290. );
  291. } else {
  292. //
  293. // Let's try the INF dir
  294. //
  295. FreePathString (userFile);
  296. userFile = JoinPaths (infDir, UserSpecifiedFile);
  297. if (DoesFileExist (userFile)) {
  298. GetFullPathName (
  299. userFile,
  300. BufferTchars,
  301. tempBuffer,
  302. &dontCare
  303. );
  304. }
  305. }
  306. }
  307. } else {
  308. //
  309. // Use the full path that the user specified
  310. //
  311. GetFullPathName (
  312. UserSpecifiedFile,
  313. BufferTchars,
  314. tempBuffer,
  315. &dontCare
  316. );
  317. if (*tempBuffer && !DoesFileExist (tempBuffer)) {
  318. *tempBuffer = 0;
  319. }
  320. }
  321. //
  322. // Transfer output into caller's buffer. Note the TCHAR conversion.
  323. //
  324. StringCopy (Buffer, tempBuffer);
  325. }
  326. __finally {
  327. if (userFile) {
  328. FreePathString (userFile);
  329. }
  330. if (tempBuffer) {
  331. FreeText (tempBuffer);
  332. }
  333. }
  334. return (Buffer && (*Buffer != 0));
  335. }
  336. VOID
  337. WriteAppStatus (
  338. IN PCTSTR AppJournal,
  339. IN DWORD Status
  340. )
  341. {
  342. HANDLE appJrnHandle;
  343. if (AppJournal && AppJournal [0]) {
  344. appJrnHandle = BfOpenFile (AppJournal);
  345. if (!appJrnHandle) {
  346. appJrnHandle = BfCreateFile (AppJournal);
  347. }
  348. if (appJrnHandle) {
  349. if (BfSetFilePointer (appJrnHandle, 0)) {
  350. BfWriteFile (appJrnHandle, (PBYTE)(&Status), sizeof (DWORD));
  351. }
  352. FlushFileBuffers (appJrnHandle);
  353. CloseHandle (appJrnHandle);
  354. }
  355. }
  356. }
  357. DWORD
  358. ReadAppStatus (
  359. IN PCTSTR AppJournal
  360. )
  361. {
  362. HANDLE appJrnHandle;
  363. DWORD result = 0;
  364. if (AppJournal && AppJournal [0]) {
  365. appJrnHandle = BfOpenReadFile (AppJournal);
  366. if (appJrnHandle) {
  367. if (BfSetFilePointer (appJrnHandle, 0)) {
  368. if (!BfReadFile (appJrnHandle, (PBYTE)(&result), sizeof (DWORD))) {
  369. result = 0;
  370. }
  371. }
  372. CloseHandle (appJrnHandle);
  373. }
  374. }
  375. return result;
  376. }
  377. VOID
  378. SelectComponentsViaInf (
  379. IN HINF Inf
  380. )
  381. {
  382. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  383. PCTSTR data;
  384. //
  385. // Enable or disable components based on the unlocalized tag name,
  386. // or by the localized string
  387. //
  388. if (InfFindFirstLine (Inf, TEXT("Disabled Components"), NULL, &is)) {
  389. do {
  390. data = InfGetStringField (&is, 1);
  391. if (data) {
  392. if (!IsmSelectComponent (data, 0, FALSE)) {
  393. IsmSelectComponent (data, COMPONENT_NAME, FALSE);
  394. }
  395. }
  396. } while (InfFindNextLine (&is));
  397. }
  398. if (InfFindFirstLine (Inf, TEXT("Enabled Components"), NULL, &is)) {
  399. do {
  400. data = InfGetStringField (&is, 1);
  401. if (data) {
  402. if (!IsmSelectComponent (data, 0, TRUE)) {
  403. IsmSelectComponent (data, COMPONENT_NAME, TRUE);
  404. }
  405. }
  406. } while (InfFindNextLine (&is));
  407. }
  408. }
  409. PARSERESULT
  410. ParseToolCmdLine (
  411. IN BOOL ScanState,
  412. OUT PTOOLARGS Args,
  413. IN INT Argc,
  414. IN PCTSTR Argv[]
  415. )
  416. {
  417. INT i;
  418. PCTSTR infFileFromCmdLine;
  419. TCHAR fullInfPath[MAX_TCHAR_PATH];
  420. MULTISZ_ENUM e;
  421. HANDLE h;
  422. BOOL logCreated = FALSE;
  423. BOOL everythingOn = TRUE;
  424. BOOL xSwitch = FALSE;
  425. #ifdef PRERELEASE
  426. DWORD tagSize;
  427. #endif
  428. ZeroMemory (Args, sizeof (TOOLARGS));
  429. Args->VerboseLevel = -1;
  430. Args->TransportName = S_RELIABLE_STORAGE_TRANSPORT;
  431. #ifdef PRERELEASE
  432. tagSize = ARRAYSIZE(Args->Tag);
  433. GetUserName (Args->Tag, &tagSize);
  434. #endif
  435. for (i = 1 ; i < Argc ; i++) {
  436. if (Argv[i][0] == TEXT('-') || Argv[i][0] == '/') {
  437. switch ((CHARTYPE) _totlower ((CHARTYPE) _tcsnextc (&Argv[i][1]))) {
  438. case TEXT('i'):
  439. if (Argv[i][2] == TEXT('x') && !Argv[i][3]) {
  440. if (ScanState) {
  441. return PARSE_OTHER_ERROR;
  442. }
  443. if (Args->NoScanStateInfs) {
  444. return PARSE_OTHER_ERROR;
  445. }
  446. Args->NoScanStateInfs = TRUE;
  447. break;
  448. }
  449. if (Argv[i][2] == TEXT(':')) {
  450. infFileFromCmdLine = &Argv[i][3];
  451. } else if (i + 1 < Argc) {
  452. i++;
  453. infFileFromCmdLine = Argv[i];
  454. } else {
  455. return PARSE_OTHER_ERROR;
  456. }
  457. if (!GetFilePath (infFileFromCmdLine, fullInfPath, ARRAYSIZE(fullInfPath))) {
  458. GbMultiSzAppend (&Args->BadInfs, infFileFromCmdLine);
  459. break;
  460. }
  461. //
  462. // Make sure fullInfPath was not already specified
  463. //
  464. if (Args->InputInf.End) {
  465. if (EnumFirstMultiSz (&e, (PCTSTR) Args->InputInf.Buf)) {
  466. do {
  467. if (StringIMatch (e.CurrentString, fullInfPath)) {
  468. GbMultiSzAppend (&Args->MultiInfs, infFileFromCmdLine);
  469. *fullInfPath = 0;
  470. break;
  471. }
  472. } while (EnumNextMultiSz (&e));
  473. }
  474. if (*fullInfPath == 0) {
  475. break;
  476. }
  477. }
  478. //
  479. // INF file is valid
  480. //
  481. GbMultiSzAppend (&Args->InputInf, fullInfPath);
  482. break;
  483. case TEXT('l'):
  484. if (Args->LogFile) {
  485. return PARSE_MULTI_LOG;
  486. }
  487. if (Argv[i][2] == TEXT(':')) {
  488. Args->LogFile = &(Argv[i][3]);
  489. } else if (i + 1 < Argc) {
  490. i++;
  491. Args->LogFile = Argv[i];
  492. } else {
  493. return PARSE_OTHER_ERROR;
  494. }
  495. h = BfCreateFile (Args->LogFile);
  496. if (!h) {
  497. return PARSE_BAD_LOG;
  498. }
  499. CloseHandle (h);
  500. logCreated = TRUE;
  501. break;
  502. case TEXT('v'):
  503. if (Args->VerboseLevel >= 0) {
  504. return PARSE_MULTI_VERBOSE;
  505. }
  506. if (Argv[i][2] == TEXT(':')) {
  507. _stscanf (&(Argv[i][3]), TEXT("%d"), &Args->VerboseLevel);
  508. } else if (i + 1 < Argc) {
  509. if (_tcsnextc (Argv[i + 1]) >= TEXT('0') &&
  510. _tcsnextc (Argv[i + 1]) <= TEXT('9')
  511. ) {
  512. i++;
  513. _stscanf (Argv[i], TEXT("%d"), &Args->VerboseLevel);
  514. } else {
  515. Args->VerboseLevel = 1;
  516. }
  517. } else {
  518. return PARSE_OTHER_ERROR;
  519. }
  520. #ifndef PRERELEASE
  521. if (Args->VerboseLevel > 7) {
  522. #else
  523. Args->VerboseLevel |= LOG_UPDATE_BIT;
  524. if (Args->VerboseLevel > 0x1F) {
  525. #endif
  526. return PARSE_OTHER_ERROR;
  527. }
  528. break;
  529. case TEXT('x'):
  530. if (xSwitch) {
  531. return PARSE_OTHER_ERROR;
  532. }
  533. if (Argv[i][2]) {
  534. return PARSE_OTHER_ERROR;
  535. }
  536. everythingOn = FALSE;
  537. xSwitch = TRUE;
  538. break;
  539. case TEXT('s'):
  540. if (Args->SystemOn) {
  541. return PARSE_OTHER_ERROR;
  542. }
  543. if (Argv[i][2]) {
  544. return PARSE_OTHER_ERROR;
  545. }
  546. Args->SystemOn = TRUE;
  547. everythingOn = FALSE;
  548. break;
  549. case TEXT('u'):
  550. if (Args->UserOn) {
  551. return PARSE_OTHER_ERROR;
  552. }
  553. if (Argv[i][2]) {
  554. return PARSE_OTHER_ERROR;
  555. }
  556. Args->UserOn = TRUE;
  557. everythingOn = FALSE;
  558. break;
  559. case TEXT('f'):
  560. if (Args->FilesOn) {
  561. return PARSE_OTHER_ERROR;
  562. }
  563. if (Argv[i][2]) {
  564. return PARSE_OTHER_ERROR;
  565. }
  566. Args->FilesOn = TRUE;
  567. everythingOn = FALSE;
  568. break;
  569. case TEXT('q'):
  570. if (ScanState) {
  571. Args->OverwriteImage = TRUE;
  572. Args->TestMode = TRUE;
  573. } else {
  574. Args->CurrentUser = TRUE;
  575. }
  576. break;
  577. case TEXT('o'):
  578. if (!ScanState) {
  579. return PARSE_OTHER_ERROR;
  580. }
  581. if (Args->OverwriteImage) {
  582. return PARSE_OTHER_ERROR;
  583. }
  584. if (Argv[i][2]) {
  585. return PARSE_OTHER_ERROR;
  586. }
  587. Args->OverwriteImage = TRUE;
  588. break;
  589. case TEXT('c'):
  590. if (Argv[i][2]) {
  591. return PARSE_OTHER_ERROR;
  592. }
  593. if (Args->ContinueOnError) {
  594. return PARSE_OTHER_ERROR;
  595. }
  596. Args->ContinueOnError = TRUE;
  597. break;
  598. case TEXT('d'):
  599. if (ScanState) {
  600. return PARSE_OTHER_ERROR;
  601. }
  602. if (Args->DelayedOpsOn) {
  603. return PARSE_OTHER_ERROR;
  604. }
  605. if (Argv[i][2]) {
  606. return PARSE_OTHER_ERROR;
  607. }
  608. Args->DelayedOpsOn = TRUE;
  609. break;
  610. case TEXT('p'):
  611. if (!ScanState) {
  612. return PARSE_OTHER_ERROR;
  613. }
  614. if (Args->FullTransport) {
  615. return PARSE_OTHER_ERROR;
  616. }
  617. if (Args->Capabilities & CAPABILITY_SPACEESTIMATE) {
  618. return PARSE_OTHER_ERROR;
  619. }
  620. Args->Capabilities |= CAPABILITY_SPACEESTIMATE;
  621. break;
  622. case TEXT('m'):
  623. switch ((CHARTYPE) _totlower (Argv[i][2])) {
  624. case TEXT('d'):
  625. if (Argv[i][3] == TEXT(':')) {
  626. Args->NewDomainName = &(Argv[i][4]);
  627. } else if (i + 1 < Argc) {
  628. i++;
  629. Args->NewDomainName = Argv[i];
  630. } else {
  631. return PARSE_OTHER_ERROR;
  632. }
  633. break;
  634. case TEXT('u'):
  635. if (Argv[i][3] == TEXT(':')) {
  636. Args->NewUserName = &(Argv[i][4]);
  637. } else if (i + 1 < Argc) {
  638. i++;
  639. Args->NewUserName = Argv[i];
  640. } else {
  641. return PARSE_OTHER_ERROR;
  642. }
  643. break;
  644. default:
  645. return PARSE_OTHER_ERROR;
  646. }
  647. break;
  648. case TEXT('h'):
  649. Args->HackHiveOn = TRUE;
  650. switch ((CHARTYPE) _totlower (Argv[i][2])) {
  651. case TEXT('p'):
  652. if (Argv[i][3] == TEXT(':')) {
  653. Args->HackProcessId = &(Argv[i][4]);
  654. } else if (i + 1 < Argc) {
  655. i++;
  656. Args->HackProcessId = Argv[i];
  657. } else {
  658. return PARSE_OTHER_ERROR;
  659. }
  660. break;
  661. case TEXT('m'):
  662. if (Argv[i][3] == TEXT(':')) {
  663. Args->HackMappedHive = &(Argv[i][4]);
  664. } else if (i + 1 < Argc) {
  665. i++;
  666. Args->HackMappedHive = Argv[i];
  667. } else {
  668. return PARSE_OTHER_ERROR;
  669. }
  670. break;
  671. default:
  672. return PARSE_OTHER_ERROR;
  673. }
  674. break;
  675. #ifdef PRERELEASE
  676. case TEXT('t'):
  677. switch ((CHARTYPE) _totlower (Argv[i][2])) {
  678. case TEXT('f'):
  679. if (Argv[i][3]) {
  680. return PARSE_OTHER_ERROR;
  681. }
  682. if (Args->FullTransport) {
  683. return PARSE_OTHER_ERROR;
  684. }
  685. Args->FullTransport = TRUE;
  686. break;
  687. case TEXT('c'):
  688. if (Argv[i][3]) {
  689. return PARSE_OTHER_ERROR;
  690. }
  691. if (Args->Capabilities & CAPABILITY_COMPRESSED) {
  692. return PARSE_OTHER_ERROR;
  693. }
  694. Args->Capabilities |= CAPABILITY_COMPRESSED;
  695. break;
  696. case TEXT('a'):
  697. if (Argv[i][3]) {
  698. return PARSE_OTHER_ERROR;
  699. }
  700. if (Args->Capabilities & CAPABILITY_AUTOMATED) {
  701. return PARSE_OTHER_ERROR;
  702. }
  703. Args->Capabilities |= CAPABILITY_AUTOMATED;
  704. break;
  705. case TEXT('i'):
  706. if (Argv[i][3] != TEXT(':')) {
  707. return PARSE_OTHER_ERROR;
  708. }
  709. StackStringCopy (Args->Tag, &Argv[i][4]);
  710. break;
  711. case 0:
  712. case TEXT(':'):
  713. if (Args->TransportNameSpecified) {
  714. return PARSE_OTHER_ERROR;
  715. }
  716. Args->TransportNameSpecified = TRUE;
  717. if (Argv[i][2]) {
  718. if (!Argv[i][3]) {
  719. return PARSE_OTHER_ERROR;
  720. }
  721. Args->TransportName = &Argv[i][3];
  722. } else {
  723. if (i + 1 >= Argc) {
  724. return PARSE_OTHER_ERROR;
  725. } else {
  726. i++;
  727. Args->TransportName = Argv[i];
  728. }
  729. }
  730. break;
  731. default:
  732. return PARSE_OTHER_ERROR;
  733. }
  734. break;
  735. case TEXT('r'):
  736. if (ScanState) {
  737. return PARSE_OTHER_ERROR;
  738. }
  739. if (Args->Recovery) {
  740. return PARSE_OTHER_ERROR;
  741. }
  742. if (Argv[i][2]) {
  743. return PARSE_OTHER_ERROR;
  744. }
  745. Args->Recovery = TRUE;
  746. break;
  747. #endif
  748. default:
  749. return PARSE_OTHER_ERROR;
  750. }
  751. } else if (!Args->StoragePath) {
  752. Args->StoragePath = Argv[i];
  753. } else {
  754. return PARSE_OTHER_ERROR;
  755. }
  756. }
  757. if (!Args->StoragePath) {
  758. if ((!Args->DelayedOpsOn) &&
  759. (!Args->HackHiveOn)
  760. ) {
  761. return PARSE_MISSING_STORAGE_PATH;
  762. }
  763. }
  764. if (everythingOn) {
  765. Args->SystemOn = TRUE;
  766. Args->UserOn = TRUE;
  767. Args->FilesOn = TRUE;
  768. }
  769. if (Args->InputInf.Buf) {
  770. GbMultiSzAppend (&Args->InputInf, TEXT(""));
  771. }
  772. return PARSE_SUCCESS;
  773. }
  774. typedef LANGID(WINAPI SETTHREADUILANGUAGE)(WORD wReserved);
  775. typedef SETTHREADUILANGUAGE *PSETTHREADUILANGUAGE;
  776. VOID
  777. CallSetThreadUILanguage (
  778. VOID
  779. )
  780. {
  781. HMODULE kernel32Dll;
  782. PSETTHREADUILANGUAGE setThreadUiLanguage = NULL;
  783. kernel32Dll = LoadLibrary (TEXT("KERNEL32.DLL"));
  784. if (kernel32Dll) {
  785. setThreadUiLanguage = (PSETTHREADUILANGUAGE) GetProcAddress (kernel32Dll, "SetThreadUILanguage");
  786. if (setThreadUiLanguage) {
  787. setThreadUiLanguage (0);
  788. }
  789. }
  790. }