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.

687 lines
21 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. hiveinit.c
  5. Abstract:
  6. Hive initialization code.
  7. Author:
  8. Bryan M. Willman (bryanwi) 12-Sep-91
  9. Environment:
  10. Revision History:
  11. Dragos C. Sambotin (dragoss) 25-Jan-99
  12. Implementation of bin-size chunk loading of hives.
  13. --*/
  14. #include "cmp.h"
  15. VOID
  16. HvpFillFileName(
  17. PHBASE_BLOCK BaseBlock,
  18. PUNICODE_STRING FileName
  19. );
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE,HvInitializeHive)
  22. #pragma alloc_text(PAGE,HvpFillFileName)
  23. #pragma alloc_text(PAGE,HvpFreeAllocatedBins)
  24. #endif
  25. // Dragos: Modified functions
  26. VOID
  27. HvpFreeAllocatedBins(
  28. PHHIVE Hive
  29. )
  30. /*++
  31. Routine Description:
  32. Free all the bins allocated for the specified hive.
  33. It applies only to stable storage. Not all bins are allocated.
  34. Those that are not allocated have BinAddress set to 0
  35. Arguments:
  36. Hive - supplies a pointer to hive control structure for hive who's bin to free.
  37. Return Value:
  38. NONE.
  39. --*/
  40. {
  41. ULONG Length;
  42. PHBIN Bin;
  43. ULONG MapSlots;
  44. ULONG Tables;
  45. PHMAP_ENTRY Me;
  46. PHMAP_TABLE Tab;
  47. ULONG i;
  48. ULONG j;
  49. //
  50. // calculate the number of tables in the map
  51. //
  52. Length = Hive->Storage[Stable].Length;
  53. MapSlots = Length / HBLOCK_SIZE;
  54. if( MapSlots > 0 ) {
  55. Tables = (MapSlots-1) / HTABLE_SLOTS;
  56. } else {
  57. Tables = 0;
  58. }
  59. if( Hive->Storage[Stable].Map ) {
  60. //
  61. // iterate through the directory
  62. //
  63. for (i = 0; i <= Tables; i++) {
  64. Tab = Hive->Storage[Stable].Map->Directory[i];
  65. ASSERT(Tab);
  66. //
  67. // iterate through the slots in the directory
  68. //
  69. for(j=0;j<HTABLE_SLOTS;j++) {
  70. Me = &(Tab->Table[j]);
  71. //
  72. // BinAddress non-zero means allocated bin
  73. //
  74. if( Me->BinAddress ) {
  75. //
  76. // a bin is freed if it is a new alloc AND it resides in paged pool
  77. //
  78. if( (Me->BinAddress & HMAP_NEWALLOC) && (Me->BinAddress & HMAP_INPAGEDPOOL) ) {
  79. Bin = (PHBIN)HBIN_BASE(Me->BinAddress);
  80. (Hive->Free)(Bin, HvpGetBinMemAlloc(Hive,Bin,Stable));
  81. }
  82. Me->BinAddress = 0;
  83. }
  84. }
  85. }
  86. }
  87. }
  88. NTSTATUS
  89. HvInitializeHive(
  90. PHHIVE Hive,
  91. ULONG OperationType,
  92. ULONG HiveFlags,
  93. ULONG FileType,
  94. PVOID HiveData OPTIONAL,
  95. PALLOCATE_ROUTINE AllocateRoutine,
  96. PFREE_ROUTINE FreeRoutine,
  97. PFILE_SET_SIZE_ROUTINE FileSetSizeRoutine,
  98. PFILE_WRITE_ROUTINE FileWriteRoutine,
  99. PFILE_READ_ROUTINE FileReadRoutine,
  100. PFILE_FLUSH_ROUTINE FileFlushRoutine,
  101. ULONG Cluster,
  102. PUNICODE_STRING FileName OPTIONAL
  103. )
  104. /*++
  105. Routine Description:
  106. Initialize a hive.
  107. Core HHive fields are always inited.
  108. File calls WILL be made BEFORE this call returns.
  109. Caller is expected to create/open files and store file handles
  110. in a way that can be derived from the hive pointer.
  111. Three kinds of initialization can be done, selected by OperationType:
  112. HINIT_CREATE
  113. Create a new hive from scratch. Will have 0 storage.
  114. [Used to do things like create HARDWARE hive and for parts
  115. of SaveKey and RestoreKey]
  116. HINIT_MEMORY_INPLACE
  117. Build a hive control structure which allows read only
  118. access to a contiguous in-memory image of a hive.
  119. No part of the image will be copied, but a map will
  120. be made.
  121. [Used by osloader.]
  122. HINIT_FLAT
  123. Support very limited (read-only, no checking code) operation
  124. against a hive image.
  125. HINIT_MEMORY
  126. Create a new hive, using a hive image already in memory,
  127. at address supplied by pointer HiveData. The data will
  128. be copied. Caller is expected to free HiveData.
  129. [Used for SYSTEM hive]
  130. HINIT_FILE
  131. Create a hive, reading its data from a file. Recovery processing
  132. via log file will be done if a log is available. If a log
  133. is recovered, flush and clear operation will proceed.
  134. HINIT_MAPFILE
  135. Create a hive, reading its data from a file. Data reading is
  136. done by mapping views of the file in the system cache.
  137. NOTE: The HHive is not a completely opaque structure, because it
  138. is really only used by a limited set of code. Do not assume
  139. that only this routine sets all of these values.
  140. Arguments:
  141. Hive - supplies a pointer to hive control structure to be initialized
  142. to describe this hive.
  143. OperationType - specifies whether to create a new hive from scratch,
  144. from a memory image, or by reading a file from disk.
  145. HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless
  146. of the types of cells allocated
  147. HIVE_NO_LAZY_FLUSH - Data in this hive is never written
  148. to disk except by an explicit FlushKey
  149. FileType - HFILE_TYPE_*, HFILE_TYPE_LOG set up for logging support respectively.
  150. HiveData - if present, supplies a pointer to an in memory image of
  151. from which to init the hive. Only useful when OperationType
  152. is set to HINIT_MEMORY.
  153. AllocateRoutine - supplies a pointer to routine called to allocate
  154. memory. WILL be called before this routine returns.
  155. FreeRoutine - supplies a pointer to routine called to free memory.
  156. CAN be called before this routine returns.
  157. FileSetSizeRoutine - supplies a pointer to a routine used to set the
  158. size of a file. CAN be called before this
  159. routine returns.
  160. FileWriteRoutine - supplies a pointer to routine called to write memory
  161. to a file.
  162. FileReadRoutine - supplies a pointer to routine called to read from
  163. a file into memory. CAN be called before this
  164. routine returns.
  165. FileFlushRoutine - supplies a pointer to routine called to flush a file.
  166. Cluster - clustering factor in HSECTOR_SIZE units. (i.e. Size of
  167. physical sector in media / HSECTOR_SIZE. 1 for 512 byte
  168. physical sectors (or smaller), 2 for 1024, 4 for 2048, etc.
  169. (Numbers greater than 8 won't work.)
  170. FileName - some path like "...\system32\config\system", last
  171. 32 or so characters will be copied into baseblock
  172. (and thus to disk) as a debugging aid. May be null.
  173. Return Value:
  174. NTSTATUS code.
  175. --*/
  176. {
  177. BOOLEAN UseForIo;
  178. PHBASE_BLOCK BaseBlock = NULL;
  179. NTSTATUS Status;
  180. ULONG i;
  181. ULONG Alignment;
  182. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INIT,"HvInitializeHive:\n"));
  183. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INIT,"\tHive=%p\n", Hive));
  184. //
  185. // reject invalid parameter combinations
  186. //
  187. if ( (! ARGUMENT_PRESENT(HiveData)) &&
  188. ((OperationType == HINIT_MEMORY) ||
  189. (OperationType == HINIT_FLAT) ||
  190. (OperationType == HINIT_MEMORY_INPLACE))
  191. )
  192. {
  193. return STATUS_INVALID_PARAMETER;
  194. }
  195. if ( ! ((OperationType == HINIT_CREATE) ||
  196. (OperationType == HINIT_MEMORY) ||
  197. (OperationType == HINIT_MEMORY_INPLACE) ||
  198. (OperationType == HINIT_FLAT) ||
  199. (OperationType == HINIT_FILE) ||
  200. (OperationType == HINIT_MAPFILE))
  201. )
  202. {
  203. return STATUS_INVALID_PARAMETER;
  204. }
  205. //
  206. // static and global control values
  207. //
  208. Hive->Signature = HHIVE_SIGNATURE;
  209. Hive->Allocate = AllocateRoutine;
  210. Hive->Free = FreeRoutine;
  211. Hive->FileSetSize = FileSetSizeRoutine;
  212. Hive->FileWrite = FileWriteRoutine;
  213. Hive->FileRead = FileReadRoutine;
  214. Hive->FileFlush = FileFlushRoutine;
  215. Hive->Log = (BOOLEAN)((FileType == HFILE_TYPE_LOG) ? TRUE : FALSE);
  216. if (Hive->Log && (HiveFlags & HIVE_VOLATILE)) {
  217. return STATUS_INVALID_PARAMETER;
  218. }
  219. Hive->HiveFlags = HiveFlags;
  220. if ((Cluster == 0) || (Cluster > HSECTOR_COUNT)) {
  221. return STATUS_INVALID_PARAMETER;
  222. }
  223. Hive->Cluster = Cluster;
  224. Hive->RefreshCount = 0;
  225. Hive->StorageTypeCount = HTYPE_COUNT;
  226. Hive->Storage[Volatile].Length = 0;
  227. #ifdef HV_TRACK_FREE_SPACE
  228. Hive->Storage[Volatile].FreeStorage = 0;
  229. #endif
  230. Hive->Storage[Volatile].Map = NULL;
  231. Hive->Storage[Volatile].SmallDir = NULL;
  232. Hive->Storage[Volatile].Guard = (ULONG)-1;
  233. Hive->Storage[Volatile].FreeSummary = 0;
  234. InitializeListHead(&Hive->Storage[Volatile].FreeBins);
  235. for (i = 0; i < HHIVE_FREE_DISPLAY_SIZE; i++) {
  236. RtlInitializeBitMap(&(Hive->Storage[Volatile].FreeDisplay[i].Display), NULL, 0);
  237. Hive->Storage[Volatile].FreeDisplay[i].RealVectorSize = 0;
  238. }
  239. Hive->Storage[Stable].Length = 0;
  240. #ifdef HV_TRACK_FREE_SPACE
  241. Hive->Storage[Stable].FreeStorage = 0;
  242. #endif
  243. Hive->Storage[Stable].Map = NULL;
  244. Hive->Storage[Stable].SmallDir = NULL;
  245. Hive->Storage[Stable].Guard = (ULONG)-1;
  246. Hive->Storage[Stable].FreeSummary = 0;
  247. InitializeListHead(&Hive->Storage[Stable].FreeBins);
  248. for (i = 0; i < HHIVE_FREE_DISPLAY_SIZE; i++) {
  249. RtlInitializeBitMap(&(Hive->Storage[Stable].FreeDisplay[i].Display), NULL, 0);
  250. Hive->Storage[Stable].FreeDisplay[i].RealVectorSize = 0;
  251. }
  252. RtlInitializeBitMap(&(Hive->DirtyVector), NULL, 0);
  253. Hive->DirtyCount = 0;
  254. Hive->DirtyAlloc = 0;
  255. Hive->LogSize = 0;
  256. Hive->BaseBlockAlloc = sizeof(HBASE_BLOCK);
  257. Hive->GetCellRoutine = HvpGetCellPaged;
  258. Hive->ReleaseCellRoutine = NULL;
  259. Hive->Flat = FALSE;
  260. Hive->ReadOnly = FALSE;
  261. UseForIo = (BOOLEAN)!(Hive->HiveFlags & HIVE_VOLATILE);
  262. //
  263. // new create case
  264. //
  265. if (OperationType == HINIT_CREATE) {
  266. BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(Hive->BaseBlockAlloc, UseForIo,CM_FIND_LEAK_TAG11));
  267. if (BaseBlock == NULL) {
  268. return STATUS_INSUFFICIENT_RESOURCES;
  269. }
  270. //
  271. // Make sure the buffer we got back is cluster-aligned. If not, try
  272. // harder to get an aligned buffer.
  273. //
  274. Alignment = Cluster * HSECTOR_SIZE - 1;
  275. if (((ULONG_PTR)BaseBlock & Alignment) != 0) {
  276. (Hive->Free)(BaseBlock, Hive->BaseBlockAlloc);
  277. BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE,CM_FIND_LEAK_TAG12));
  278. if (BaseBlock == NULL) {
  279. return STATUS_INSUFFICIENT_RESOURCES;
  280. }
  281. Hive->BaseBlockAlloc = PAGE_SIZE;
  282. }
  283. BaseBlock->Signature = HBASE_BLOCK_SIGNATURE;
  284. BaseBlock->Sequence1 = 1;
  285. BaseBlock->Sequence2 = 1;
  286. BaseBlock->TimeStamp.HighPart = 0;
  287. BaseBlock->TimeStamp.LowPart = 0;
  288. BaseBlock->Major = HSYS_MAJOR;
  289. BaseBlock->Minor = HSYS_MINOR;
  290. BaseBlock->Type = HFILE_TYPE_PRIMARY;
  291. BaseBlock->Format = HBASE_FORMAT_MEMORY;
  292. BaseBlock->RootCell = HCELL_NIL;
  293. BaseBlock->Length = 0;
  294. BaseBlock->Cluster = Cluster;
  295. BaseBlock->CheckSum = 0;
  296. HvpFillFileName(BaseBlock, FileName);
  297. Hive->BaseBlock = BaseBlock;
  298. Hive->Version = HSYS_MINOR;
  299. Hive->BaseBlock->BootType = 0;
  300. return STATUS_SUCCESS;
  301. }
  302. //
  303. // flat image case
  304. //
  305. if (OperationType == HINIT_FLAT) {
  306. Hive->BaseBlock = (PHBASE_BLOCK)HiveData;
  307. Hive->Version = Hive->BaseBlock->Minor;
  308. Hive->Flat = TRUE;
  309. Hive->ReadOnly = TRUE;
  310. Hive->GetCellRoutine = HvpGetCellFlat;
  311. Hive->Storage[Stable].Length = Hive->BaseBlock->Length;
  312. Hive->StorageTypeCount = 1;
  313. Hive->BaseBlock->BootType = 0;
  314. // don't init this as we don't need it!!!
  315. //Status = HvpAdjustHiveFreeDisplay(Hive,Hive->Storage[Stable].Length,Stable);
  316. return STATUS_SUCCESS;
  317. }
  318. //
  319. // readonly image case
  320. //
  321. if (OperationType == HINIT_MEMORY_INPLACE) {
  322. BaseBlock = (PHBASE_BLOCK)HiveData;
  323. if ( (BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) ||
  324. (BaseBlock->Type != HFILE_TYPE_PRIMARY) ||
  325. (BaseBlock->Major != HSYS_MAJOR) ||
  326. (BaseBlock->Minor > HSYS_MINOR_SUPPORTED) ||
  327. (BaseBlock->Format != HBASE_FORMAT_MEMORY) ||
  328. (BaseBlock->Sequence1 != BaseBlock->Sequence2) ||
  329. (HvpHeaderCheckSum(BaseBlock) !=
  330. (BaseBlock->CheckSum))
  331. )
  332. {
  333. return STATUS_REGISTRY_CORRUPT;
  334. }
  335. Hive->BaseBlock = BaseBlock;
  336. Hive->Version = BaseBlock->Minor;
  337. Hive->ReadOnly = TRUE;
  338. Hive->StorageTypeCount = 1;
  339. Hive->BaseBlock->BootType = 0;
  340. Status = HvpAdjustHiveFreeDisplay(Hive,BaseBlock->Length,Stable);
  341. if( !NT_SUCCESS(Status) ) {
  342. return Status;
  343. }
  344. if ( !NT_SUCCESS(HvpBuildMap(
  345. Hive,
  346. (PUCHAR)HiveData + HBLOCK_SIZE
  347. )))
  348. {
  349. return STATUS_REGISTRY_CORRUPT;
  350. }
  351. return(STATUS_SUCCESS);
  352. }
  353. //
  354. // memory copy case
  355. //
  356. if (OperationType == HINIT_MEMORY) {
  357. BaseBlock = (PHBASE_BLOCK)HiveData;
  358. if ( (BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) ||
  359. (BaseBlock->Type != HFILE_TYPE_PRIMARY) ||
  360. (BaseBlock->Format != HBASE_FORMAT_MEMORY) ||
  361. (BaseBlock->Major != HSYS_MAJOR) ||
  362. (BaseBlock->Minor > HSYS_MINOR_SUPPORTED) ||
  363. (HvpHeaderCheckSum(BaseBlock) !=
  364. (BaseBlock->CheckSum))
  365. )
  366. {
  367. return STATUS_REGISTRY_CORRUPT;
  368. }
  369. Hive->BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(Hive->BaseBlockAlloc, UseForIo,CM_FIND_LEAK_TAG13));
  370. if (Hive->BaseBlock==NULL) {
  371. return(STATUS_INSUFFICIENT_RESOURCES);
  372. }
  373. //
  374. // Make sure the buffer we got back is cluster-aligned. If not, try
  375. // harder to get an aligned buffer.
  376. //
  377. Alignment = Cluster * HSECTOR_SIZE - 1;
  378. if (((ULONG_PTR)Hive->BaseBlock & Alignment) != 0) {
  379. (Hive->Free)(Hive->BaseBlock, Hive->BaseBlockAlloc);
  380. Hive->BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE,CM_FIND_LEAK_TAG14));
  381. if (Hive->BaseBlock == NULL) {
  382. return (STATUS_INSUFFICIENT_RESOURCES);
  383. }
  384. Hive->BaseBlockAlloc = PAGE_SIZE;
  385. }
  386. RtlCopyMemory(Hive->BaseBlock, BaseBlock, HSECTOR_SIZE);
  387. Hive->BaseBlock->BootRecover = BaseBlock->BootRecover;
  388. Hive->BaseBlock->BootType = BaseBlock->BootType;
  389. Hive->Version = Hive->BaseBlock->Minor;
  390. Status = HvpAdjustHiveFreeDisplay(Hive,BaseBlock->Length,Stable);
  391. if( !NT_SUCCESS(Status) ) {
  392. (Hive->Free)(Hive->BaseBlock, Hive->BaseBlockAlloc);
  393. Hive->BaseBlock = NULL;
  394. return Status;
  395. }
  396. if ( !NT_SUCCESS(HvpBuildMapAndCopy(Hive,
  397. (PUCHAR)HiveData + HBLOCK_SIZE))) {
  398. (Hive->Free)(Hive->BaseBlock, Hive->BaseBlockAlloc);
  399. Hive->BaseBlock = NULL;
  400. return STATUS_REGISTRY_CORRUPT;
  401. }
  402. HvpFillFileName(Hive->BaseBlock, FileName);
  403. return(STATUS_SUCCESS);
  404. }
  405. #ifndef CM_ENABLE_MAPPED_VIEWS
  406. if( OperationType == HINIT_MAPFILE ) {
  407. OperationType = HINIT_FILE;
  408. }
  409. #endif //CM_ENABLE_MAPPED_VIEWS
  410. //
  411. // file read case
  412. //
  413. if (OperationType == HINIT_FILE) {
  414. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvInitializeHive(%wZ,HINIT_FILE) :\n", FileName));
  415. //
  416. // get the file image (possible recovered via log) into memory
  417. //
  418. Status = HvLoadHive(Hive);
  419. if ((Status != STATUS_SUCCESS) && (Status != STATUS_REGISTRY_RECOVERED)) {
  420. return Status;
  421. }
  422. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n"));
  423. if (Status == STATUS_REGISTRY_RECOVERED) {
  424. //
  425. // We have a good hive, with a log, and a dirty map,
  426. // all set up. Only problem is that we need to flush
  427. // the file so the log can be cleared and new writes
  428. // posted against the hive. Since we know we have
  429. // a good log in hand, we just write the hive image.
  430. //
  431. if ( ! HvpDoWriteHive(Hive, HFILE_TYPE_PRIMARY)) {
  432. //
  433. // DRAGOS: Here we need cleanup
  434. // Clean up the bins already allocated
  435. //
  436. HvpFreeAllocatedBins( Hive );
  437. return STATUS_REGISTRY_IO_FAILED;
  438. }
  439. //
  440. // If we get here, we have recovered the hive, and
  441. // written it out to disk correctly. So we clear
  442. // the log here.
  443. //
  444. RtlClearAllBits(&(Hive->DirtyVector));
  445. Hive->DirtyCount = 0;
  446. (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, 0,0);
  447. Hive->LogSize = 0;
  448. }
  449. //
  450. // slam debug name data into base block
  451. //
  452. HvpFillFileName(Hive->BaseBlock, FileName);
  453. return STATUS_SUCCESS;
  454. }
  455. //
  456. // file map case
  457. //
  458. if (OperationType == HINIT_MAPFILE) {
  459. Hive->GetCellRoutine = HvpGetCellMapped;
  460. Hive->ReleaseCellRoutine = HvpReleaseCellMapped;
  461. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvInitializeHive(%wZ,HINIT_MAPFILE) :\n", FileName));
  462. Status = HvMapHive(Hive);
  463. if ((Status != STATUS_SUCCESS) && (Status != STATUS_REGISTRY_RECOVERED)) {
  464. return Status;
  465. }
  466. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n"));
  467. if (Status == STATUS_REGISTRY_RECOVERED) {
  468. //
  469. // We have a good hive, with a log, and a dirty map,
  470. // all set up. Only problem is that we need to flush
  471. // the file so the log can be cleared and new writes
  472. // posted against the hive. Since we know we have
  473. // a good log in hand, we just write the hive image.
  474. //
  475. if ( ! HvpDoWriteHive(Hive, HFILE_TYPE_PRIMARY)) {
  476. //
  477. // DRAGOS: Here we need cleanup
  478. // Clean up the bins already allocated
  479. //
  480. HvpFreeAllocatedBins( Hive );
  481. return STATUS_REGISTRY_IO_FAILED;
  482. }
  483. //
  484. // If we get here, we have recovered the hive, and
  485. // written it out to disk correctly. So we clear
  486. // the log here.
  487. //
  488. RtlClearAllBits(&(Hive->DirtyVector));
  489. Hive->DirtyCount = 0;
  490. (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, 0,0);
  491. Hive->LogSize = 0;
  492. }
  493. //
  494. // slam debug name data into base block
  495. //
  496. HvpFillFileName(Hive->BaseBlock, FileName);
  497. return STATUS_SUCCESS;
  498. }
  499. return STATUS_INVALID_PARAMETER;
  500. }
  501. VOID
  502. HvpFillFileName(
  503. PHBASE_BLOCK BaseBlock,
  504. PUNICODE_STRING FileName
  505. )
  506. /*++
  507. Routine Description:
  508. Zero out the filename portion of the base block.
  509. If FileName is not NULL, copy last 64 bytes into name tail
  510. field of base block
  511. Arguments:
  512. BaseBlock - supplies pointer to a base block
  513. FileName - supplies pointer to a unicode STRING
  514. Return Value:
  515. None.
  516. --*/
  517. {
  518. ULONG offset;
  519. ULONG length;
  520. PUCHAR sptr;
  521. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_HIVE,"HvpFillFileName: %wZ\n", FileName));
  522. RtlZeroMemory((PVOID)&(BaseBlock->FileName[0]), HBASE_NAME_ALLOC);
  523. if (FileName == NULL) {
  524. return;
  525. }
  526. //
  527. // Account for 0 at the end, so we have nice debug spews
  528. //
  529. if (FileName->Length < HBASE_NAME_ALLOC) {
  530. offset = 0;
  531. length = FileName->Length;
  532. } else {
  533. offset = FileName->Length - HBASE_NAME_ALLOC + sizeof(WCHAR);
  534. length = HBASE_NAME_ALLOC - sizeof(WCHAR);
  535. }
  536. sptr = (PUCHAR)&(FileName->Buffer[0]);
  537. RtlCopyMemory(
  538. (PVOID)&(BaseBlock->FileName[0]),
  539. (PVOID)&(sptr[offset]),
  540. length
  541. );
  542. }