48

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?

3
  • 2
    Possible duplicate of Can I set hiberfil.sys to another drive?
    – PJTraill
    Sep 2, 2016 at 12:50
  • You can't. But you can disable hibernation (powercfg.exe -h off), and then delete the file.
    – Ian Boyd
    Jul 10, 2018 at 13:55
  • If you are interested, it involves at least two steps, the second which I am trying to simplify for us without IDA (disassembly/assembly) access.
    – Mark C
    Dec 27, 2021 at 5:34

2 Answers 2

44

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.

8
  • 15
    To bad windows can't handle this, I'd really need it for my SSD. I hope that they fix it in the future so you can choose where to put it like in Mac OS X.
    – Hultner
    Jun 29, 2011 at 11:41
  • 5
    Yah, in my opinion it's a bit of a design flaw. Even if the system needs to boot from the main drive, there's just no reason to have to store all the gigabytes of information on the same drive- the hibernation file could load the basics (e.g. drive access) and then look to another drive for additional data. Unfortunately, they didn't design it to handle that case- which means they won't until a new OS... if ever.
    – Namey
    Sep 21, 2011 at 16:19
  • 1
    @Namey: If the hibernation file could load the basics, then it might as well be written straight into the boot loader in the first place. Then you open up a whole nother can of worms. On another not, I wouldn't consider it a design flaw either. It was written back in the days of Windows NT I presume, where speed, memory limits, and low CPU power were the big factors, not small SSD drives. Heck, who would of predicted SSDs being so common in the first place??
    – surfasb
    Oct 27, 2011 at 6:31
  • 3
    That's a stupid excuse of microsoft. What if both disks are on the same controller - same driver is used? what if one disk is ssd and you don't want to wear it fast?
    – NickSoft
    Oct 4, 2013 at 12:01
  • 2
    @NickSoft, Exactly. Nothing is stopping the "miniature file system driver" from being able to recognize other disk drives. Nothing, except for pure lazyness and the typical Microsoft cost-cutting approach to maximize Micro$oft returns.
    – Pacerier
    Oct 24, 2015 at 0:21
7

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.

5
  • Talk about a cryptic answer not many can understand !
    – killjoy
    Aug 14, 2018 at 20:24
  • Did anyone try to patch ntoskrnl.exe this way? Did it work afterwards?
    – PF4Public
    Oct 25, 2019 at 19:48
  • So, disabling Default/Administrative share c$ didn't work, disabling powercfg and linking didn't work either. BCD change is applied. How do I apply this patch the same way? (6.1.7601.24545)
    – Mark C
    Dec 27, 2021 at 9:06
  • 2
    Oh dear changing this is far away from being 'userfriendly'. Even I by myself did not fully tested this. Maybe there was some problem in the way like the need to also patch bootmgr or some signature check that was triggered by patching ntioskrnl or bootmgr that I couldn't find and disarm. However I was just fascinated by the challenge and just for fund went into Windows Internals. These are my 'findings'.
    – Nadu
    Jan 22, 2022 at 20:00
  • There are multiple integrity checks of the kernel binary, the PE checksum is only the beginning.
    – Milind R
    Aug 20 at 21:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .