How to change location of hibernation file in Windows 7?

I can't enable hibernation in Windows 7 because there is not enough room on my C: drive to create the hibernation file. How can I make Windows put the file somewhere else?


Solution 1:

You can't, it has to be in the root of the boot drive (the C: drive in your case).

Raymond Chen explained the reasons why in this Windows Confidential article: The File System Paradox.

Hibernation follows a similar pattern. Hibernating the operating system means dumping the entire contents of memory into the hibernation file; restoring from hibernation entails sucking that file back into memory and pretending nothing happened. Again, it's another chicken-and-egg problem: to load the hibernation file, you need the file system driver, but the file system driver is in the hibernation file. If you keep the hibernation file in the root directory of the boot drive, the miniature file system driver can be used instead.

Solution 2:

Okay there are 2 thing to solve to move hiberfil.sys

  1. Tell 'ntoskrnl.exe' that runs as Process 'System' to open/save hibernation data to D:\hiberfil.sys instead of C:\ ->unsolved yet !

  2. To apply this chance also to the boot configuration Data file (c:\BOOT\BCD) -> This is relatively easy with Tools like the VisualBCD https://www.boyans.net/DownloadVisualBCD.html -> Or even just using regedit editing HKLM\BCD00000000\Objects{71575733-c376-11e4-80ea-806e6f6e6963}\Elements\21000001 that is the HiberFileDrive of the ResumeLoader Or \22000002 HiberFilePath. Maybe you need to use 'File/Load hive' c:\BOOT\BCD to mount the 'BCD00000000' branch.(Cursor needs to be on HKLM, else to menu item is greyed out) -> as it seem this is already done by ntosknl.exe so there is no need no use in changing this since ya changes will be overwritten.

However number 1. is the worse and more hard to change thing. Hmm let's load ntoskrnl.exe into IDA and located the function that deals with /hiberfil.sys and decompile it to see what exactly is going on there...

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

Okay in short the path is hardcoded like this: IoArcBootDeviceName + "\hiberfil.sys" without some nasty binary patching there is no way to change that. Well beside touching the holy windows grail patching the "ntoskernel" might result in problems like updates undo the patch or Antivirus programs might get crazy... However let's see what references are the to IoArcBootDeviceName:

IopLoadCrashdumpDriver PopDeleteHiberFile PopCreateHiberFile PopBcdSetupResumeObject PopBcdSetDefaultResumeObjectElements PopBcdSetPendingResume PopBcdRegenerateResumeObject PopBcdEstablishResumeObject PopAllocateHiberContext IopCreateArcNames PopBcdSetupResumeObject

Wow changing that seem to be fine (only thing that goes off a little is IopLoadCrashdumpDriver System32\Drivers\crashdmp.sys however who needs crashdump - doesn't matter if we break something there)

So patching IopCreateArcNames that creates ArcBootDeviceName will be fine:

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 I'm using ntkrnlmp.exe 6.1.7601.19045 from Win7 64 bit and checked this code against ReactOS. (However the hibernating part is yet not implemented in the Reactos sources) Note that ArcBootDeviceName will be something like: \Device\Harddisk1\Partition0

Hmm let's patch ArcBootDeviceName(LoaderBlock + 0x78) to ArcHalDeviceName(LoaderBlock + 0x80)

So in case the bootmgr loader is on a different partition than windows hopefully hibernate.sys is creates were bootmgr is.

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

So in ntoskrnl.exe replace 4C8B4B78 with 4C8B4B80 at two locations. Don't forget to fix PE-Checksum afterwards.