Jak zmienić lokalizację pliku hibernacji w systemie Windows 7?

45

Nie mogę włączyć hibernacji w systemie Windows 7, ponieważ na moim dysku C: nie ma wystarczającej ilości miejsca, aby utworzyć plik hibernacji. Jak mogę zmusić system Windows do umieszczenia pliku w innym miejscu?

Zjawisko
źródło
Nie możesz Ale możesz wyłączyć hibernację ( powercfg.exe -h off), a następnie usunąć plik.
Ian Boyd,

Odpowiedzi:

42

Nie możesz, musi znajdować się w katalogu głównym dysku rozruchowego (w Twoim przypadku dysk C:).

Raymond Chen wyjaśnił powody, dla których w tym poufnym artykule dotyczącym systemu Windows: Paradoks systemu plików .

Hibernacja przebiega podobnie. Hibernacja systemu operacyjnego oznacza zrzucenie całej zawartości pamięci do pliku hibernacji; przywracanie ze stanu hibernacji pociąga za sobą zasysanie tego pliku z powrotem do pamięci i udawanie, że nic się nie wydarzyło. Znowu jest to kolejny problem z kurczakiem i jajkiem: aby załadować plik hibernacji, potrzebujesz sterownika systemu plików, ale sterownik systemu plików znajduje się w pliku hibernacji. Jeśli plik hibernacji jest przechowywany w katalogu głównym dysku rozruchowego, można zamiast niego użyć miniaturowego sterownika systemu plików.

Snark
źródło
14
Aby złe okna nie mogły sobie z tym poradzić, naprawdę potrzebowałbym tego na dysku SSD. Mam nadzieję, że naprawią go w przyszłości, więc możesz wybrać, gdzie go umieścić, jak w Mac OS X.
Hultner
5
Tak, moim zdaniem jest to wada projektowa. Nawet jeśli system wymaga rozruchu z dysku głównego, nie ma po prostu powodu, aby przechowywać wszystkie gigabajty informacji na tym samym dysku - plik hibernacji może załadować podstawy (np. Dostęp do dysku), a następnie szukać innego dysku w celu uzyskania dodatkowych dane. Niestety, nie zaprojektowali go do obsługi tej skrzynki - co oznacza, że ​​zrobią to dopiero w nowym systemie operacyjnym ... jeśli w ogóle.
Namey
1
@Namey: Jeśli plik hibernacji może załadować podstawy, to równie dobrze można go zapisać bezpośrednio w module ładującym rozruch. Następnie otwieracie całą kolejną puszkę robaków. Z drugiej strony nie uważam, że to wada projektowa. Przypuszczalnie został napisany w czasach Windows NT, w których szybkość, ograniczenia pamięci i mała moc procesora były głównymi czynnikami, a nie małymi dyskami SSD. Heck, kto by przewidywał, że dyski SSD są tak powszechne?
surfasb
1
To tylko ładne słowa o „kurczaku i jajach”, co nie ma znaczenia: jeśli moduł ładujący wie, jak załadować plik hibernacji z dysku do pamięci, nie ma powodu, aby nie mieć sterownika systemu plików wewnątrz modułu ładującego.
Denis Barmenkov
3
To głupia wymówka Microsoft. Co się stanie, jeśli oba dyski są na tym samym kontrolerze - używany jest ten sam sterownik? co jeśli jeden dysk jest ssd i nie chcesz go szybko nosić?
NickSoft,
6

Dobrze, są 2 rzeczy do rozwiązania, aby przenieść hiberfil.sys

  1. Powiedz „ntoskrnl.exe”, który działa jako „System” procesu, aby otworzyć / zapisać dane hibernacji w D: \ hiberfil.sys zamiast C: \ -> jeszcze nierozwiązane!

  2. Aby zastosować tę szansę również do pliku danych konfiguracji rozruchu (c: \ BOOT \ BCD) -> Jest to stosunkowo łatwe w przypadku narzędzi takich jak VisualBCD https://www.boyans.net/DownloadVisualBCD.html -> Lub nawet po prostu za pomocą regedit edycja HKLM \ BCD00000000 \ Objects {71575733-c376-11e4-80ea-806e6f6e6963} \ Elements \ 21000001, czyli HiberFileDrive z ResumeLoader lub \ 22000002 HiberFilePath. Być może musisz użyć „File / Load hive” c: \ BOOT \ BCD, aby zamontować gałąź „BCD00000000”. (Kursor musi być na HKLM, w przeciwnym razie pozycja menu jest wyszarzona) -> wydaje się, że jest to już zrobione przez ntosknl.exe, więc nie ma potrzeby zmieniać tego, ponieważ zmiany zostaną zastąpione.

Jednak numer 1. jest gorszy i trudniejszy do zmiany. Hmm, załadujmy ntoskrnl.exe do IDA i zlokalizowaliśmy funkcję, która zajmuje się /hiberfil.sys i dekompilujemy go, aby zobaczyć, co dokładnie tam się dzieje ...

__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,
...

W skrócie, ścieżka jest zakodowana na stałe w następujący sposób: IoArcBootDeviceName + "\ hiberfil.sys" bez jakiejś paskudnej łatki binarnej nie ma sposobu, aby to zmienić. Oprócz dotknięcia świętego Graala Windows łatającego „ntoskernel” może to powodować problemy, takie jak cofanie aktualizacji lub programy antywirusowe mogą zwariować ... Zobaczmy jednak, jakie są odniesienia do IoArcBootDeviceName:

IopLoadCrashdumpDriver PopDeleteHiberFile PopCreateHiberFile PopBcdSetupResumeObject PopBcdSetDefaultResumeObjectElements PopBcdSetPendingResume PopBcdRegenerateResumeObject PopBcdEstablishRextEumeEbateRextEume

Wow, zmiana wydaje się być w porządku (jedyną rzeczą, która trochę się psuje, jest IopLoadCrashdumpDriver System32 \ Drivers \ crashdmp.sys, ale kto potrzebuje zrzutu awaryjnego - nie ma znaczenia, jeśli coś tam zepsujemy)

Tak więc łatanie IopCreateArcNames, które tworzy ArcBootDeviceName, będzie w porządku:

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 btw Używam ntkrnlmp.exe 6.1.7601.19045 z Win7 64 bit i sprawdziłem ten kod pod ReactOS. (Jednak hibernująca część nie jest jeszcze zaimplementowana w źródłach Reactos). Uwaga: ArcBootDeviceName będzie wyglądać tak: \ Device \ Harddisk1 \ Partition0

Hmm, załatajmy ArcBootDeviceName (LoaderBlock + 0x78) na ArcHalDeviceName (LoaderBlock + 0x80)

Więc w przypadku, gdy moduł ładujący bootmgr znajduje się na innej partycji niż Windows, mam nadzieję, że utworzy się hibernate.sys, gdzie jest 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

Tak więc w ntoskrnl.exe zamień 4C8B4B78 na 4C8B4B80 w dwóch lokalizacjach. Nie zapomnij później naprawić sumy kontrolnej PE.

Nadu
źródło
Mów o tajemniczej odpowiedzi, której niewielu może zrozumieć!
killjoy
Czy ktoś próbował załatać ntoskrnl.exe w ten sposób? Czy to zadziałało później?
PF4Public