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.

484 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dynupdt.c
  5. Abstract:
  6. Dynamic Update support for text setup. Portions moved from i386\win31upg.c
  7. Author:
  8. Ovidiu Temereanca (ovidiut) 20-Aug-2000
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. //
  14. // Macros
  15. //
  16. #define MAX_SECTION_NAME_LENGTH 14
  17. #define UPDATES_SECTION_NAME L"updates"
  18. #define UNIPROC_SECTION_NAME L"uniproc"
  19. //
  20. // Globals
  21. //
  22. HANDLE g_UpdatesCabHandle = NULL;
  23. PVOID g_UpdatesSifHandle = NULL;
  24. HANDLE g_UniprocCabHandle = NULL;
  25. PVOID g_UniprocSifHandle = NULL;
  26. WCHAR
  27. SpExtractDriveLetter(
  28. IN PWSTR PathComponent
  29. );
  30. BOOLEAN
  31. SpInitAlternateSource (
  32. VOID
  33. )
  34. {
  35. PWSTR p;
  36. NTSTATUS Status;
  37. ULONG ErrorLine;
  38. WCHAR updatesCab[MAX_PATH];
  39. WCHAR updatesSif[MAX_PATH];
  40. WCHAR updatesSifSection[MAX_SECTION_NAME_LENGTH];
  41. WCHAR uniprocCab[MAX_PATH];
  42. WCHAR uniprocSif[MAX_PATH];
  43. WCHAR uniprocSifSection[MAX_SECTION_NAME_LENGTH];
  44. BOOLEAN bUniprocCab = FALSE;
  45. BOOLEAN b = FALSE;
  46. //
  47. // look if section [SetupParams] has an UpdatedSources key
  48. //
  49. p = SpGetSectionKeyIndex (WinntSifHandle, SIF_SETUPPARAMS, SIF_UPDATEDSOURCES, 0);
  50. if (!p) {
  51. return FALSE;
  52. }
  53. p = SpNtPathFromDosPath (p);
  54. if (!p) {
  55. goto exit;
  56. }
  57. wcscpy (updatesCab, p);
  58. wcscpy (updatesSif, updatesCab);
  59. p = wcsrchr (updatesSif, L'.');
  60. if (!p) {
  61. p = wcsrchr (updatesSif, 0);
  62. }
  63. wcscpy (p, L".sif");
  64. //
  65. // load the sif
  66. //
  67. Status = SpLoadSetupTextFile (
  68. updatesSif,
  69. NULL, // No image already in memory
  70. 0, // Image size is empty
  71. &g_UpdatesSifHandle,
  72. &ErrorLine,
  73. FALSE,
  74. FALSE
  75. );
  76. if (!NT_SUCCESS (Status)) {
  77. KdPrintEx((
  78. DPFLTR_SETUP_ID,
  79. DPFLTR_ERROR_LEVEL,
  80. "SETUP: SpInitAlternateSource: Unable to read %ws. ErrorLine = %ld, Status = %lx \n",
  81. updatesSif,
  82. ErrorLine,
  83. Status
  84. ));
  85. goto exit;
  86. }
  87. wcscpy (updatesSifSection, UPDATES_SECTION_NAME);
  88. if (!SpSearchTextFileSection (g_UpdatesSifHandle, updatesSifSection) ||
  89. SpCountLinesInSection (g_UpdatesSifHandle, updatesSifSection) == 0) {
  90. KdPrintEx((
  91. DPFLTR_SETUP_ID,
  92. DPFLTR_ERROR_LEVEL,
  93. "SETUP: SpInitAlternateSource: Section [%ws] not found or empty in %ws.\n",
  94. updatesSifSection,
  95. updatesSif
  96. ));
  97. goto exit;
  98. }
  99. p = SpGetSectionKeyIndex (WinntSifHandle, SIF_SETUPPARAMS, SIF_UPDATEDSOURCES, 1);
  100. if (p && *p) {
  101. p = SpNtPathFromDosPath (p);
  102. if (!p) {
  103. goto exit;
  104. }
  105. wcscpy (uniprocCab, p);
  106. wcscpy (uniprocSif, uniprocCab);
  107. p = wcsrchr (uniprocSif, L'.');
  108. if (!p) {
  109. p = wcsstr (uniprocSif, 0);
  110. }
  111. wcscpy (p, L".sif");
  112. //
  113. // load the sif
  114. //
  115. Status = SpLoadSetupTextFile (
  116. uniprocSif,
  117. NULL, // No image already in memory
  118. 0, // Image size is empty
  119. &g_UniprocSifHandle,
  120. &ErrorLine,
  121. FALSE,
  122. FALSE
  123. );
  124. if (!NT_SUCCESS (Status)) {
  125. KdPrintEx((
  126. DPFLTR_SETUP_ID,
  127. DPFLTR_ERROR_LEVEL,
  128. "SETUP: SpInitAlternateSource: Unable to read %ws. ErrorLine = %ld, Status = %lx \n",
  129. uniprocSif,
  130. ErrorLine,
  131. Status
  132. ));
  133. goto exit;
  134. }
  135. wcscpy (uniprocSifSection, UNIPROC_SECTION_NAME);
  136. if (!SpSearchTextFileSection (g_UniprocSifHandle, uniprocSifSection) ||
  137. SpCountLinesInSection (g_UniprocSifHandle, uniprocSifSection) == 0) {
  138. KdPrintEx((
  139. DPFLTR_SETUP_ID,
  140. DPFLTR_ERROR_LEVEL,
  141. "SETUP: SpInitAlternateSource: Section [%ws] not found or empty in %ws.\n",
  142. uniprocSifSection,
  143. uniprocSif
  144. ));
  145. goto exit;
  146. }
  147. bUniprocCab = TRUE;
  148. }
  149. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpInitAlternateSource: Using alternate sources: %ws\n", updatesCab));
  150. b = SpInitializeUpdatesCab (
  151. updatesCab,
  152. updatesSifSection,
  153. bUniprocCab ? uniprocCab : NULL,
  154. bUniprocCab ? uniprocSifSection : NULL
  155. );
  156. exit:
  157. if (!b) {
  158. SpUninitAlternateSource ();
  159. }
  160. return b;
  161. }
  162. VOID
  163. SpUninitAlternateSource (
  164. VOID
  165. )
  166. {
  167. if (g_UpdatesSifHandle) {
  168. SpFreeTextFile (g_UpdatesSifHandle);
  169. g_UpdatesSifHandle = NULL;
  170. }
  171. if (g_UniprocSifHandle) {
  172. SpFreeTextFile (g_UniprocSifHandle);
  173. g_UniprocSifHandle = NULL;
  174. }
  175. }
  176. BOOLEAN
  177. SpInitializeUpdatesCab (
  178. IN PWSTR UpdatesCab,
  179. IN PWSTR UpdatesSifSection,
  180. IN PWSTR UniprocCab,
  181. IN PWSTR UniprocSifSection
  182. )
  183. {
  184. PWSTR CabFileSection;
  185. NTSTATUS Status;
  186. PWSTR DriverCabName, DriverCabPath;
  187. OBJECT_ATTRIBUTES Obja;
  188. UNICODE_STRING UnicodeString;
  189. IO_STATUS_BLOCK IoStatusBlock;
  190. CABDATA *MyCabData, *MyList = NULL;
  191. DWORD i;
  192. BOOLEAN b = TRUE;
  193. INIT_OBJA (&Obja, &UnicodeString, UpdatesCab);
  194. Status = ZwCreateFile (&g_UpdatesCabHandle,
  195. FILE_GENERIC_READ,
  196. &Obja,
  197. &IoStatusBlock,
  198. NULL,
  199. FILE_ATTRIBUTE_NORMAL,
  200. FILE_SHARE_READ,
  201. FILE_OPEN,
  202. 0,
  203. NULL,
  204. 0 );
  205. if (!NT_SUCCESS (Status)) {
  206. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open cab file %ws. Status = %lx \n", UpdatesCab, Status));
  207. return FALSE;
  208. }
  209. //
  210. // create the list entry
  211. //
  212. MyCabData = SpMemAlloc (sizeof(CABDATA));
  213. MyCabData->CabName = SpDupStringW (UpdatesCab);
  214. MyCabData->CabHandle = g_UpdatesCabHandle;
  215. MyCabData->CabSectionName = SpDupStringW (UpdatesSifSection);
  216. MyCabData->CabInfHandle = g_UpdatesSifHandle;
  217. MyCabData->Next = MyList;
  218. MyList = MyCabData;
  219. if (UniprocCab) {
  220. INIT_OBJA (&Obja, &UnicodeString, UniprocCab);
  221. Status = ZwCreateFile (&g_UniprocCabHandle,
  222. FILE_GENERIC_READ,
  223. &Obja,
  224. &IoStatusBlock,
  225. NULL,
  226. FILE_ATTRIBUTE_NORMAL,
  227. FILE_SHARE_READ,
  228. FILE_OPEN,
  229. 0,
  230. NULL,
  231. 0 );
  232. if (!NT_SUCCESS (Status)) {
  233. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open cab file %ws. Status = %lx \n", UniprocCab, Status));
  234. b = FALSE;
  235. goto exit;
  236. }
  237. //
  238. // create the list entry
  239. //
  240. MyCabData = SpMemAlloc (sizeof(CABDATA));
  241. MyCabData->CabName = SpDupStringW (UniprocCab);
  242. MyCabData->CabHandle = g_UniprocCabHandle;
  243. MyCabData->CabSectionName = SpDupStringW (UniprocSifSection);
  244. MyCabData->CabInfHandle = g_UniprocSifHandle;
  245. MyCabData->Next = MyList;
  246. MyList = MyCabData;
  247. }
  248. exit:
  249. if (b) {
  250. //
  251. // insert it at the beginning
  252. //
  253. while (MyList && MyList->Next) {
  254. MyList = MyList->Next;
  255. }
  256. if (MyList) {
  257. MyList->Next = CabData;
  258. CabData = MyList;
  259. }
  260. } else {
  261. //
  262. // destroy MyList
  263. //
  264. while (MyList) {
  265. MyCabData = MyList->Next;
  266. MyList = MyCabData;
  267. SpMemFree (MyCabData->CabName);
  268. SpMemFree (MyCabData->CabSectionName);
  269. SpMemFree (MyCabData);
  270. }
  271. }
  272. return b;
  273. }
  274. PWSTR
  275. SpNtPathFromDosPath (
  276. IN PWSTR DosPath
  277. )
  278. {
  279. PDISK_REGION region;
  280. WCHAR drive[_MAX_DRIVE];
  281. WCHAR dir[_MAX_DIR];
  282. WCHAR fname[_MAX_FNAME];
  283. WCHAR ext[_MAX_EXT];
  284. PWSTR p;
  285. if (!DosPath) {
  286. return NULL;
  287. }
  288. region = SpPathComponentToRegion (DosPath);
  289. if (!region) {
  290. return NULL;
  291. }
  292. if (DosPath[2] != L'\\') {
  293. return NULL;
  294. }
  295. SpNtNameFromRegion (region, TemporaryBuffer, ELEMENT_COUNT(TemporaryBuffer), PartitionOrdinalCurrent);
  296. wcscat (TemporaryBuffer, DosPath + 2);
  297. return SpDupStringW (TemporaryBuffer);
  298. }
  299. PDISK_REGION
  300. SpPathComponentToRegion(
  301. IN PWSTR PathComponent
  302. )
  303. /*++
  304. Routine Description:
  305. This routine attempts to locate a region descriptor for a
  306. given DOS path component. If the DOS path component does
  307. not start with x:, then this fails.
  308. Arguments:
  309. PathComponent - supplies a component from the DOS search path,
  310. for which a region esacriptor is desired.
  311. Return Value:
  312. Pointer to disk region; NULL if none found with drive letter
  313. that starts the dos component.
  314. --*/
  315. {
  316. WCHAR c;
  317. ULONG disk;
  318. PDISK_REGION region;
  319. c = SpExtractDriveLetter(PathComponent);
  320. if(!c) {
  321. return(NULL);
  322. }
  323. for(disk=0; disk<HardDiskCount; disk++) {
  324. for(region=PartitionedDisks[disk].PrimaryDiskRegions; region; region=region->Next) {
  325. if(region->DriveLetter == c) {
  326. ASSERT(region->PartitionedSpace);
  327. return(region);
  328. }
  329. }
  330. //
  331. // Do not see extended partition on PC98.
  332. //
  333. for(region=PartitionedDisks[disk].ExtendedDiskRegions; region; region=region->Next) {
  334. if(region->DriveLetter == c) {
  335. ASSERT(region->PartitionedSpace);
  336. return(region);
  337. }
  338. }
  339. }
  340. return(NULL);
  341. }
  342. WCHAR
  343. SpExtractDriveLetter(
  344. IN PWSTR PathComponent
  345. )
  346. {
  347. WCHAR c;
  348. if((wcslen(PathComponent) >= 2) && (PathComponent[1] == L':')) {
  349. c = RtlUpcaseUnicodeChar(PathComponent[0]);
  350. if((c >= L'A') && (c <= L'Z')) {
  351. return(c);
  352. }
  353. }
  354. return(0);
  355. }
  356. PWSTR
  357. SpGetDynamicUpdateBootDriverPath(
  358. IN PWSTR NtBootPath,
  359. IN PWSTR NtBootDir,
  360. IN PVOID InfHandle
  361. )
  362. /*++
  363. Routine Description:
  364. Gets the dynamic update boot driver directory's root
  365. path.
  366. Arguments:
  367. NtBootPath - Boot path in NT namespace
  368. NtBootDir - Boot directory under boot path (like $WIN_NT$.~BT)
  369. InfHandle - Winnt.sif handle
  370. Return Value:
  371. Returns the dynamic update boot driver root path if successful
  372. otherwise returns NULL
  373. --*/
  374. {
  375. PWSTR DriverDir = NULL;
  376. if (NtBootPath && NtBootDir && InfHandle) {
  377. PWSTR Present = SpGetSectionKeyIndex(InfHandle,
  378. WINNT_SETUPPARAMS_W,
  379. WINNT_SP_DYNUPDTBOOTDRIVERPRESENT_W,
  380. 0);
  381. PWSTR Dir = SpGetSectionKeyIndex(InfHandle,
  382. WINNT_SETUPPARAMS_W,
  383. WINNT_SP_DYNUPDTBOOTDRIVERROOT_W,
  384. 0);
  385. if (Dir && Present && !_wcsicmp(Present, L"yes")) {
  386. WCHAR Buffer[MAX_PATH];
  387. wcscpy(Buffer, NtBootPath);
  388. SpConcatenatePaths(Buffer, NtBootDir);
  389. //
  390. // NOTE : Currently ignore boot driver root path
  391. //
  392. // SpConcatenatePaths(Buffer, Dir);
  393. DriverDir = SpDupStringW(Buffer);
  394. }
  395. }
  396. return DriverDir;
  397. }