題 如何在Windows 7中更改休眠文件的位置?


我無法在Windows 7中啟用休眠,因為我的C:驅動器上沒有足夠的空間來創建休眠文件。如何讓Windows將文件放在其他位置?


43
2017-12-19 12:23


起源


可能重複 我可以將hiberfil.sys設置為另一個驅動器嗎? - PJTraill
你不能。但你可以禁用休眠(powercfg.exe -h off),然後刪除該文件。 - Ian Boyd


答案:


你不能,它必須在啟動驅動器的根目錄(在你的情況下C:驅動器)。

Raymond Chen在這篇Windows機密文章中解釋了原因: 文件系統悖論

休眠遵循類似的模式。   休眠操作系統意味著   轉儲內存的全部內容   進入休眠文件;恢復   從冬眠中吸取吮吸   歸檔到內存並假裝   沒啥事兒。再一次,這是另一個   雞蛋問題:裝雞蛋   休眠文件,你需要的文件   系統驅動程序,但文件系統   驅動程序處於休眠文件中。如果   你保持休眠文件在   啟動驅動器的根目錄,   微型文件系統驅動程序即可   用來代替。


41
2017-12-19 13:15



對於壞窗口無法處理這個問題,我真的需要它用於我的SSD。我希望他們將來能夠修復它,以便你可以選擇在Mac OS X中放置它。 - Hultner
是的,在我看來這是一個設計缺陷。即使系統需要從主驅動器啟動,也沒有理由必須在同一個驅動器上存儲所有千兆字節的信息 - 休眠文件可以加載基礎知識(例如驅動器訪問),然後查看另一個驅動器以獲取額外的數據。不幸的是,他們沒有設計它來處理這種情況 - 這意味著他們不會在新的操作系統之前......如果有的話。 - Namey
@Namey:如果休眠文件可以加載基礎知識,那麼它也可以直接寫入引導加載程序。然後你打開了一整套蠕蟲。另一方面,我不認為這是一個設計缺陷。它是在我假設的Windows NT時代寫的,其中速度,內存限制和低CPU功率是重要因素,而不是小型SSD驅動器。哎呀,誰會預測SSD首先如此普遍? - surfasb
這只是關於“雞和雞蛋”的漂亮話語並不重要:如果引導加載程序知道如何將hibernate文件從磁盤加載到內存,則沒有理由不在引導加載程序中安裝文件系統驅動程序。 - Denis Barmenkov
這是微軟的一個愚蠢的藉口。如果兩個磁盤在同一個控制器上 - 使用相同的驅動程序怎麼辦?如果一個磁盤是ssd並且你不想快速磨損怎麼辦? - NickSoft


好吧,移動hiberfil.sys有兩件事要解決

  1. 告訴'ntoskrnl.exe'作為進程'系統'運行,打開/保存休眠數據到D:\ hiberfil.sys而不是C:\ - >尚未解決!

  2. 將此機會也應用於引導配置數據文件(c:\ BOOT \ BCD) - >使用像VisualBCD這樣的工具相對容易 https://www.boyans.net/DownloadVisualBCD.html - >甚至只是使用regedit編輯 HKLM \ BCD00000000 \對象{71575733-c376-11e4-80ea-806e6f6e6963} \元素\ 21000001 這是ResumeLoader的HiberFileDrive或\ 22000002 HiberFilePath。 也許你需要使用'File / Load hive'c:\ BOOT \ BCD來掛載'BCD00000000'分支。(光標需要在HKLM上,否則菜單項是灰色的) - >因為它似乎已經由ntosknl.exe完成了所以沒有必要改變它,因為你的更改將被覆蓋。

然而,數字1更糟糕,更難以改變。 嗯,讓我們將ntoskrnl.exe加載到IDA中並找到處理/hiberfil.sys的函數並對其進行反編譯以查看其中究竟發生了什麼...

__int64 __fastcall PopCreateHiberFile(LARGE_INTEGER *a1)
{
...
 RtlInitUnicodeString(&Source, L"\\hiberfil.sys");
...
  RtlAppendUnicodeStringToString(&Destination, &IoArcBootDeviceName);
  RtlAppendUnicodeStringToString(&Destination, &Source);
...
  ObjectAttributes.RootDirectory = 0i64;
  ObjectAttributes.Attributes = 576;
  ObjectAttributes.ObjectName = &Destination;
  ObjectAttributes.SecurityDescriptor = v5;
  ObjectAttributes.SecurityQualityOfService = 0i64;
  ret_2 = IoCreateFile(
            &FileHandle,
            0x100003u,
            &ObjectAttributes,
...

好吧,簡而言之,路徑是硬編碼的: IoArcBootDeviceName +“\ hiberfil.sys” 沒有一些令人討厭的二進制修補,沒有辦法改變它。 好在旁邊觸摸聖潔的窗戶聖杯 修補“ntoskernel”可能會導致更新等問題撤消補丁或防病毒程序可能會變得瘋狂...... 但是,讓我們看看IoArcBootDeviceName的引用是什麼:

IopLoadCrashdumpDriver PopDeleteHiberFile PopCreateHiberFile PopBcdSetupResumeObject PopBcdSetDefaultResumeObjectElements PopBcdSetPendingResume PopBcdRegenerateResumeObject PopBcdEstablishResumeObject PopAllocateHiberContext IopCreateArcNames PopBcdSetupResumeObject

哇改變那似乎很好 (只有一點點是IopLoadCrashdumpDriver System32 \ Drivers \ crashdmp.sys然而誰需要crashdump - 如果我們在那裡打破一些並不重要)

修補 IopCreateArcNames 這創造了 ArcBootDeviceName 會沒事的:

NTSTATUS INIT_FUNCTION NTAPI IopCreateArcNames  (   IN PLOADER_PARAMETER_BLOCK  LoaderBlock )   
...
   /* Create the global system partition name */
   63     sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
   64     RtlInitAnsiString(&ArcString, Buffer);
   65     RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
   66 
   67     /* Allocate memory for the string */
   68     Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
   69     IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
   70                                                       Length,
   71                                                       TAG_IO);
   72     if (IoLoaderArcBootDeviceName)
   73     {
   74         /* Copy the name */
   75         RtlCopyMemory(IoLoaderArcBootDeviceName,
   76                       LoaderBlock->ArcBootDeviceName,
   77                       Length);
   78     }

...

https://doxygen.reactos.org/d3/d82/ntoskrnl_2io_2iomgr_2arcname_8c.html 順便說一句,我正在使用Win7 64位的ntkrnlmp.exe 6.1.7601.19045,並針對ReactOS檢查此代碼。 (但是冬眠部分尚未在Reactos源中實現) 請注意,ArcBootDeviceName將類似於: \設備\ Harddisk1的\ Partition0

嗯,我們將ArcBootDeviceName(LoaderBlock + 0x78)修補為ArcHalDeviceName(LoaderBlock + 0x80)

因此,如果bootmgr加載器位於與windows不同的分區上,希望hibernate.sys創建的是bootmgr。

1405A9C15 4C 8B 4B 78                    mov     r9, [rbx+78h]
Patch #1           80

1405A9C19 4C 8D 05 30 06+                lea     r8, aArcnameS   ; "\\ArcName\\%s"
1405A9C20 48 8D 4C 24 40                 lea     rcx, [rsp+0D8h+pszDest] ; pszDest
1405A9C25 48 8B D7                       mov     rdx, rdi        ; cchDest
1405A9C28 E8 E3 AE B6 FF                 call    RtlStringCchPrintfA

...
1405A9C41 48 8D 0D C0 E7+                lea     rcx, IoArcBootDeviceName ; DestinationString
1405A9C48 41 B0 01                       mov     r8b, 1          ; AllocateDestinationString
1405A9C4B E8 60 13 DB FF                 call    RtlAnsiStringToUnicodeString
1405A9C50 48 8B 7B 78                    mov     rdi, [rbx+78h]
Patch #2           80

所以在ntoskrnl.exe中用4C8B4B80替換4C8B4B78兩個位置。不要忘記事後修復PE-Checksum。


6
2018-05-31 21:13



談論一個沒有多少人能理解的神秘答案! - killjoy