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.

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