Paragon gpt_loader.sys BSOD analysis and fix
Update 27.09.2019
I forgot to patch an entry in the relocation table, causing a 0xc000001d bugcheck,
as soon as the driver is relocated. This is fixed now, sorry for the inconvenience.
Update 29.03.2014
I found a better solution that the one published 2 days ago which should really
fix the problem. In case that you downloaded and used the patcher earlier,
please copy back the gpt_loader.sys.bak that the patcher generated in your
SYSTEM32\Drivers directory to gpt_loader.sys, download the new patcher and
patch again.
The Problem
I recently came across a Bugcheck 0x00000024 (NTFS_FILE_SYSTEM) in
gpt_loader.sys on a friend’s PC.
gpt_loader.sys is a driver that belongs to Paragon GPT Loader
which allows a Windows XP user to use drives with a capacity over
2TB (which isn’t normally possible). This software also comes bundled
with Hiatchi-drives.
This driver hasn’t been updated since the end of 2010 (Version 8.0.1.0) and
unfortunately has a very nasty bug:
On high I/O loads on the target drive, the driver sometimes crashes with
a BSOD, if read/write-Operations are performed at sectors above the
2TB Limit, as it seems. That would explain, why the problem hasn’t occured
earlier but starts to get problematic with the drive being filled more and
more:
BUGCHECK 0x00000024 (0x001902FE, 0xB73A5D00,0xB73A59FC,0xBA92E9E2) BA92E92E base at BA928000
It seems that there are more people with this problem, but until now,
no fix has been found :
The analysis
So I was forced to analyze the probem myself using a minidump. I loaded
it into WinDbg and found the following interesting parts:
eax=00000000 ebx=89d69e70 ecx=ae1d5c38 edx=00000000 esi=89d69f4c edi=8af0f978 eip=b810e9e6 esp=ae1d5bac ebp=ae1d5bc4 iopl=0 nv up ei pl nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202 gpt_lo_1+0x69e6: b810e9e6 80480301 or byte ptr [eax+3],1 ds:0023:00000003=??
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
STACK_TEXT: WARNING: Stack unwind information not available. Following frames may be wrong. ae1d5bc4 b810ea5d ae1d5c38 89d69e70 ae1d5d34 gpt_lo_1+0x69e6 ae1d5bd4 b810f3d7 ae1d5c38 89d69e70 89d69e70 gpt_lo_1+0x6a5d ae1d5d34 b7781411 89d69f4c 89d69e70 89eb2950 gpt_lo_1+0x73d7 ae1d5e00 804ef1f9 8af769e0 89d69f4c 89bc5bf8 fltsrv+0x4411
...
So this is a classic NULL-Pointer dereferencing bug.
I therefore loaded the driver into the disassembler and found the
following code in the function where it crashed:
Now let’s have a look at the position where it crashed:
.text:00016942 ; int __stdcall Z3TbGptLoader__irpReadWrite(int, PIRP Irp)
.text:00016942 sub_16942 proc near ; DATA XREF: .rdata:0001897Co
.text:00016942 ; .rdata:00018A1Co
.text:00016942
.text:00016942 var_C = dword ptr -0Ch
.text:00016942 var_8 = dword ptr -8
.text:00016942 var_1 = byte ptr -1
.text:00016942 arg_0 = dword ptr 8
.text:00016942 Irp = byte ptr 0Ch
.text:00016942
.text:00016942 mov edi, edi
.text:00016944 push ebp
.text:00016945 mov ebp, esp
.text:00016947 sub esp, 0Ch
.text:0001694A push ebx
.text:0001694B mov ebx, dword ptr [ebp+Irp]
.text:0001694E push esi
.text:0001694F mov esi, [ebx+60h]
.text:00016952 cmp byte ptr [esi], 3
.text:00016955 push edi
.text:00016956 setz [ebp+var_1]
.text:0001695A mov edi, ecx
.text:0001695C xor ecx, ecx
.text:0001695E xor eax, eax
.text:00016960 mov [ebp+var_C], ecx
.text:00016963 cmp [edi+7Ch], ecx
.text:00016966 jz short loc_1698B
.text:00016968 mov ebx, [edi+7Ch]
.text:0001696B push ecx
.text:0001696C push ebx
.text:0001696D push dword ptr [esi+10h]
.text:00016970 push dword ptr [esi+0Ch]
.text:00016973 call _alldiv
.text:00016978 mov ecx, edx
.text:0001697A mov [ebp+var_C], eax
.text:0001697D mov eax, [esi+4]
.text:00016980 xor edx, edx
.text:00016982 div ebx
.text:00016984 mov ebx, dword ptr [ebp+Irp]
.text:00016987 test ecx, ecx
.text:00016989 jnz short loc_1699E
.text:0001698B
.text:0001698B loc_1698B: ; CODE XREF: sub_16942+24j
.text:0001698B xor edx, edx
.text:0001698D add eax, [ebp+var_C]
.text:00016990 adc edx, ecx
.text:00016992 mov [ebp+var_8], edx
.text:00016995 js short loc_169A7
.text:00016997 jg short loc_1699E
.text:00016999 cmp eax, 0FFFFFFFFh
.text:0001699C jbe short loc_169A7
.text:0001699E
.text:0001699E loc_1699E: ; CODE XREF: sub_16942+47j
.text:0001699E ; sub_16942+55j
.text:0001699E cmp byte ptr [edi+0E2h], 0
.text:000169A5 jnz short loc_169C1
.text:000169A7
.text:000169A7 loc_169A7: ; CODE XREF: sub_16942+53j
.text:000169A7 ; sub_16942+5Aj
.text:000169A7 cmp [ebp+var_1], 0
.text:000169AB push ebx
.text:000169AC push [ebp+arg_0]
.text:000169AF mov ecx, edi
.text:000169B1 jz short loc_169BA
.text:000169B3 call sub_12B96
.text:000169B8 jmp short loc_16A37
.text:000169BA ; ---------------------------------------------------------------------------
.text:000169BA
.text:000169BA loc_169BA: ; CODE XREF: sub_16942+6Fj
.text:000169BA call sub_12B96
.text:000169BF jmp short loc_16A37
.text:000169C1 ; ---------------------------------------------------------------------------
.text:000169C1
.text:000169C1 loc_169C1: ; CODE XREF: sub_16942+63j
.text:000169C1 lea eax, [ebp+Irp]
.text:000169C4 push eax ; Irp
.text:000169C5 lea ecx, [edi+0FCh]
.text:000169CB call sub_166B2
.text:000169D0 test al, al
.text:000169D2 jz short loc_169F4
.text:000169D4 lea ecx, [edi+20h] ; Tag
.text:000169D7 call sub_10A04
.text:000169DC mov eax, [ebx+60h]
.text:000169DF mov ecx, [ebp+arg_0]
.text:000169E2 or byte ptr [eax+3], 1 ; CRASH!!!
.text:000169E6 add edi, 11Ch
.text:000169EC push edi
.text:000169ED call sub_11B14
.text:000169F2 jmp short loc_16A37
.text:000169F4 ; ---------------------------------------------------------------------------
.text:000169F4
.text:000169F4 loc_169F4: ; CODE XREF: sub_16942+90j
.text:000169F4 mov eax, dword_19024
.text:000169F9 mov esi, [eax]
.text:000169FB mov [ebp+var_8], eax
.text:000169FE cmp esi, eax
.text:00016A00 jz short loc_16A21
eax is obviously NULL from what we can see from the WinDbg output.
eax in turn is the pointer found at ebx+60h.
ebx is dword ptr [ebp+Irp], as we can also verify from
the Windbg output regarding registers and stack.
When checking the call stack, we can soon find out that this is
a handler function for the IRP_MJ_WRITE request.
Now we can apply the IRP-Structure from NTDDK to it and we find
out that ebx+60h actually is the member:
struct _IO_STACK_LOCATION *CurrentStackLocation;
So basically this resembles the call to IoGetCurrentIrpStackLocation().
Byte 3 there is the Control-Member, so the OR here tries to add
1 (SL_PENDING_RETURNED) to the Flags. This is what the DDK macro IoMarkIrpPending does.
When reading the docs to IRP_MJ_WRITE, we are told that this member
has to be set upon this IRP, so why the heck is it NULL there?
The next thing, that can be checked, is, if it was really NULL upon
function entry. As it gets already dereferenced at 00016952, it must
have been sane there, otherwise the crash would have occured there:
.text:0001694F mov esi, [ebx+60h] .text:00016952 cmp byte ptr [esi], 3
So the reason for the crash must be somewhere within that location
and 000169E2 where the crash finally occurs.
The only reference that we can see here which does not just read
the contents of the CurrentStackLocation is at 000169C1, where a
pointer to it gets loaded into register eax and then passed to the
function sub_166B2 via the stack:
.text:000169C1 lea eax, [ebp+Irp] .text:000169C4 push eax ; Irp .text:000169C5 lea ecx, [edi+0FCh] .text:000169CB call sub_166B2
Now let’s see what this function does:
.text:000166B2 ; int __stdcall AddIRPToList(KIRQL NewIrql) .text:000166B2 sub_166B2 proc near ; CODE XREF: sub_16942+8Dp .text:000166B2 ; sub_16B7E+20p .text:000166B2 .text:000166B2 NewIrql = byte ptr 8 .text:000166B2 .text:000166B2 mov edi, edi .text:000166B4 push ebp .text:000166B5 mov ebp, esp .text:000166B7 push esi .text:000166B8 push edi .text:000166B9 push 0 ; PoolType .text:000166BB push 0Ch ; NumberOfBytes .text:000166BD mov esi, ecx .text:000166BF call sub_16E36 ; ExAllocatePoolWithTag .text:000166C4 pop ecx .text:000166C5 pop ecx .text:000166C6 test eax, eax .text:000166C8 jz short loc_166D6 .text:000166CA mov ecx, dword ptr [ebp+NewIrql] .text:000166CD mov ecx, [ecx] .text:000166CF mov [eax+8], ecx .text:000166D2 mov edi, eax .text:000166D4 jmp short loc_166D8 .text:000166D6 ; --------------------------------------------------------------------------- .text:000166D6 .text:000166D6 loc_166D6: ; CODE XREF: sub_166B2+16j .text:000166D6 xor edi, edi .text:000166D8 .text:000166D8 loc_166D8: ; CODE XREF: sub_166B2+22j .text:000166D8 test edi, edi .text:000166DA jnz short loc_166E0 .text:000166DC xor al, al .text:000166DE jmp short loc_16712 .text:000166E0 ; --------------------------------------------------------------------------- .text:000166E0 .text:000166E0 loc_166E0: ; CODE XREF: sub_166B2+28j .text:000166E0 push ebx .text:000166E1 lea ebx, [esi+1Ch] .text:000166E4 mov ecx, ebx ; SpinLock .text:000166E6 call sub_1631C ; AcquireSpinLock .text:000166EB mov [ebp+NewIrql], al .text:000166EE mov eax, [esi+4] .text:000166F1 push dword ptr [ebp+NewIrql] ; NewIrql .text:000166F4 mov [edi], esi .text:000166F6 mov [edi+4], eax .text:000166F9 mov [eax], edi .text:000166FB mov ecx, ebx ; SpinLock .text:000166FD mov [esi+4], edi .text:00016700 call sub_1634C ; ReleaseSpinLock .text:00016705 push 0 ; int .text:00016707 lea ecx, [esi+8] ; Semaphore .text:0001670A call sub_16398 ; ReleaseSemaphore .text:0001670F mov al, 1 .text:00016711 pop ebx .text:00016712 .text:00016712 loc_16712: ; CODE XREF: sub_166B2+2Cj .text:00016712 pop edi .text:00016713 pop esi .text:00016714 pop ebp .text:00016715 retn 4 .text:00016715 sub_166B2 endp
Don’t get confused by the misleading name NewIrql, in fact it’s still our
PIRP pointer.
It also has 2 parameters, not one. First one is a pointer to the start
of a linked IRP-list, partly seems the be a structure like this:
typedef struct tag_PENDINGIRPS { LIST_ENTRY ListHead; KSEMAPHORE Semaphore; // +8 KSPIN_LOCK Lock; // +28 } PENDINGIRPS;
And the second parameter is our PIRP.
What this function basically does (here as C-Code for easier understanding):
typedef struct tag_IRPLIST { LIST_ENTRY ListHead; PIRP *Irp; // +8 } IRPLIST, *PIRPLIST; BOOL AddIRPToList(PENDINGIRPS *pIrps, PIRP **ppMyIrp) { PIRPLIST pList; if (pList = ExAllocatePoolWithTag(sizeof(IRPLIST), NonPagedPool)) { KIRQL irql; pList->Irp = *ppMyIrp; irql = AcquireSpinlock(&pIrps->Lock); InsertTailList(&pIrps->ListHead, pList); ReleaseSpinLock(&pIrps->Lock, irql); KeReleaseSemaphore(&pIrps->Semaphore, 1, 1, FALSE); return TRUE; } return FASE; }
So this function acquires a mutex and then adds our PIRP to some
linked list, presumably for processing by another worker.
As adding to the list is done secured by spinlocks, this tells us
that we are not the only one messing with the list at the same time.
Additionally there is a Semaphore that gets triggered after adding, which makes
us believe that this finally fires up the processing of the IRP.
As the bugcheck clearly shows that CurrentStackLocation member of our
IRP is NULL, we must assume that the worker is consuming and
completing our IRP from the list, before we can add 1 to the
CurrentStackLocation->Control member resulting in the given NULL pointer
dereference.
Upon further investigation, we can actually find the routine that is
processing the entries in the list ( I named some functions to
better specify what they are doing):
.text:00016A6A IRPProcessingLoop proc near ; DATA XREF: .rdata:00018980o .text:00016A6A ; .rdata:00018A20o .text:00016A6A mov edi, edi .text:00016A6C push ebx .text:00016A6D push esi .text:00016A6E mov esi, ecx .text:00016A70 lea ebx, [esi+0FCh] .text:00016A76 mov ecx, ebx .text:00016A78 call GetNextIRPFromList .text:00016A7D test eax, eax .text:00016A7F jz short loc_16AAC .text:00016A81 push edi .text:00016A82 lea edi, [esi+20h] .text:00016A85 .text:00016A85 loc_16A85: ; CODE XREF: IRPProcessingLoop+3Fj .text:00016A85 mov edx, [esi] .text:00016A87 push eax .text:00016A88 mov ecx, esi .text:00016A8A call dword ptr [edx+8Ch] .text:00016A90 cmp byte ptr [edi+18h], 0 .text:00016A94 jnz short loc_16AA0 .text:00016A96 push 18h ; RemlockSize .text:00016A98 push edi ; Tag .text:00016A99 push edi ; RemoveLock .text:00016A9A call ds:IoReleaseRemoveLockEx .text:00016AA0 .text:00016AA0 loc_16AA0: ; CODE XREF: IRPProcessingLoop+2Aj .text:00016AA0 mov ecx, ebx .text:00016AA2 call GetNextIRPFromList .text:00016AA7 test eax, eax .text:00016AA9 jnz short loc_16A85 .text:00016AAB pop edi .text:00016AAC .text:00016AAC loc_16AAC: ; CODE XREF: IRPProcessingLoop+15j .text:00016AAC pop esi .text:00016AAD xor eax, eax .text:00016AAF pop ebx .text:00016AB0 retn .text:00016AB0 IRPProcessingLoop endp .text:00016AB0 .text:00016AB0 ; --------------------------------------------------------------------------- .text:00016AB1 db 5 dup(0CCh)
If we transform the function to C-Code, this would read like:
int __fastcall IRPProcessingLoop(my_class *this) { PIRP irp; for (irp = GetNextIRPFromList(this->PendingIRPs); irp; irp = GetNextIRPFromList(this->PendingIRPs) ) { this->lpVtbl->processIRP(this, irp); if ( !this->b56) IoReleaseRemoveLock(&this->IORemoveLock, &this->IORemoveLock); } return 0; }
So now take a look at the function that I call GetNextIRPFromList:
.text:0001665E GetNextIRPFromList proc near ; CODE XREF: FreeIRPList+14p .text:0001665E ; IRPProcessingLoop+Ep ... .text:0001665E .text:0001665E var_8 = dword ptr -8 .text:0001665E NewIrql = byte ptr -4 .text:0001665E .text:0001665E mov edi, edi .text:00016660 push ebp .text:00016661 mov ebp, esp .text:00016663 push ecx .text:00016664 push ecx .text:00016665 push ebx .text:00016666 push esi .text:00016667 push edi .text:00016668 mov esi, ecx .text:0001666A lea edi, [esi+8] .text:0001666D push edi ; Semaphore .text:0001666E call ds:KeReadStateSemaphore .text:00016674 mov ecx, edi ; Object .text:00016676 call WaitForSingleObject .text:0001667B lea ebx, [esi+1Ch] .text:0001667E mov ecx, ebx ; SpinLock .text:00016680 call AcquireSpinlock .text:00016685 mov edi, [esi] .text:00016687 mov [ebp+NewIrql], al .text:0001668A mov eax, [edi+8] .text:0001668D push dword ptr [ebp+NewIrql] ; NewIrql .text:00016690 mov [ebp+var_8], eax .text:00016693 mov eax, [edi] .text:00016695 mov [esi], eax .text:00016697 mov ecx, ebx ; SpinLock .text:00016699 mov [eax+4], esi .text:0001669C call ReleaseSpinlock .text:000166A1 push edi ; NewIrql .text:000166A2 call FreePoolWithTag .text:000166A7 mov eax, [ebp+var_8] .text:000166AA pop ecx .text:000166AB pop edi .text:000166AC pop esi .text:000166AD pop ebx .text:000166AE leave .text:000166AF retn .text:000166AF GetNextIRPFromList endp
Translating it to more readable C-Code reveals how it works:
struct _IO_STACK_LOCATION *__fastcall GetNextIRPFromList(PENDINGIRPS *pIrps) { KIRQL irql; IRPLIST Entry; PIRP irp; KeReadStateSemaphore(&pIrps->Semaphore); WaitForSingleObject(&pIrps->Semaphore); irql = AcquireSpinlock(&pIrps->Lock); Entry = RemoveHeadList(&pIrps->ListHead); irp = Entry->IrpStackLocation; ReleaseSpinLock(&pIrps->Lock, irql); FreePoolWithTag(Entry); return irp; }
So it’s clearly waiting for the Semaphore that is set in AddIRPToList.
Now for the sake of completeness, let’s also translate the Z3TbGptLoader__irpReadWrite
function to some sort of readable C-code so tht we can finally see
what’s going on here and how to fix it. I didn’t do a full translation
of this, as we are only interested in the relevant parts:
int __thiscall Z3TbGptLoader__irpReadWrite(my_class *this, int a2, PIRP Irp)
{
if (this->dw226 && this->dw124 &&
/* Some unnown division, no time to find out what it does, doesn't matter
for us */
Irp->CurrentStackLocation->Parameters.Write.ByteOffset / this->dw124
! (Irp->CurrentStackLocation->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE &&
Irp->CurrentStackLocation->Parameters.Write.ByteOffset.HighPart == -1)
{
if (AddIRPToList(this->PendingIRPs, &Irp))
{
AcquireRemoveLock(&this->IORemoveLock);
IoMarkIrpPending(Irp);
EndThis(arg2, this->lpVtbl->Func284);
}
else
{
AddErrorToSyslog("Z3TbGptLoader::irpReadWrite", ...);
Irp->IoStatus.Status = STATUS_NO_MEMORY;
EndThis(arg2, this->lpVtbl->IRPProcessingLoop);
}
}
else
{
EndThis(arg2, this->lpVtbl->PassOn);
}
}
So putting one and one together, we see what’s going wrong here:
AddIRPToList triggers the semaphore to process the IRP, after
it has added it to the list, but in irpReadWrite, it is attempted to
modify the IRP afterwards (mark IRP pending by setting control-member)
and acquiring a remove lock.
Fixing it
Now how to fix the bug?
First we can see from WinDbg output, that ESI still holds a pointer to
the CurrentStackLocation, so wo could just change
.text:000169E2 or byte ptr [eax+3], 1
to
.text:000169E2 or byte ptr [esi+3], 1
But that wouldn’t be a proper fix, because maybe the pointer may not
be valid anymore at that time and additionally, the intention of the
code is to set that control flag before the IRP gets processed by the worker
thread.
So we must think about a different solution.
First guess would be that we could just set it in AddIRPToList.
But this doesn’t work out well, because the function is also called
at in another funtion, so no luck with that. Additionally, we learned
from above that there is also a RemoveLock in place which also should
be set before the IRP is being processed.
Let’s have a look at this other function that is calling AddIRPToList
which I called close_driver:
.text:00016B82 close_driver proc near ; CODE XREF: sub_15DC2+Ep .text:00016B82 ; sub_16C60+8p .text:00016B82 .text:00016B82 NewIrql = byte ptr -4 .text:00016B82 .text:00016B82 mov edi, edi .text:00016B84 push ebp .text:00016B85 mov ebp, esp .text:00016B87 push ecx .text:00016B88 and dword ptr [ebp+NewIrql], 0 .text:00016B8C push esi .text:00016B8D mov esi, ecx .text:00016B8F push edi .text:00016B90 lea eax, [ebp+NewIrql] .text:00016B93 lea edi, [esi+0FCh] .text:00016B99 push eax ; NewIrql .text:00016B9A mov ecx, edi .text:00016B9C mov dword ptr [esi], offset off_18998 .text:00016BA2 call AddIRPToList .text:00016BA7 test al, al .text:00016BA9 jz short loc_16BB6 .text:00016BAB lea ecx, [esi+128h] .text:00016BB1 call DoWaitForSingleObject .text:00016BB6 .text:00016BB6 loc_16BB6: ; CODE XREF: close_driver+27j .text:00016BB6 lea ecx, [esi+148h] .text:00016BBC call sub_16722 .text:00016BC1 lea ecx, [esi+128h] .text:00016BC7 call DoCloseHandle .text:00016BCC lea ecx, [esi+11Ch] .text:00016BD2 call sub_16722 .text:00016BD7 mov ecx, edi .text:00016BD9 call FreeIRPList .text:00016BDE mov ecx, esi .text:00016BE0 call sub_12BB2 .text:00016BE5 pop edi .text:00016BE6 pop esi .text:00016BE7 leave .text:00016BE8 retn .text:00016BE8 close_driver endp .text:00016BE8 ; --------------------------------------------------------------------------- .text:00016BE9 db 5 dup(0CCh)
Now the following idea arises:
1) Remove the KeReleaseSemaphore from AddIRPToList.
2) Release the Semaphore in irpReadWrite AFTER PIRP was
setup correctly.
3) Modify close_driver to also do a manual KeReleaseSemaphore
after AddIRPToList so that the call to it really can be removed
from that function.
Let’s see if there is sufficient space for this. Have a look at AddIRPToList
and check what’s done there:
.text:00016705 push 0 ; int .text:00016707 lea ecx, [esi+8] ; Semaphore .text:0001670A call sub_16398 ; ReleaseSemaphore
So semaphore is loaded into ECX, The PUSH 0 takes 2 bytes,
the CALL to ReleaseSemaphore takes 5 bytes, in total 7 bytes provided
that we can reuse ecx after function call, which fortuntely is the case
as ECX doesn’t get restored at function end of AddIRPToList.
First let’s check the possibility for close_driver:
We have 5 bytes in alignment space AFTER the function end.
Too bad, that’s not enough.. Now what to do.. Fortunately
the MS C ompiler always generates a pointless 2 Byte mov edi, edi
instruction at the start of each function whic actually is meant
to be used for a detour hook in case someone wants to patch the
function during update -> Success, we have 7 bytes!
Now we can move up the function by 2 bytes, then insert our
call to ReleseSemaphore and we’re set.
Next, let’s chec irpReadWrite:
We can save 2 bytes by the fact that
.text:000169DC mov eax, [ebx+60h]
is unnecessary, as we already have the pointer to it in esi.
Not enough, though. But let’s have a look above that function for a moment:
.text:000169AF mov ecx, edi .text:000169B1 jz short loc_169BA .text:000169B3 call sub_12B96 .text:000169B8 jmp short loc_16A37 .text:000169BA ; --------------------------------------------------------------------------- .text:000169BA .text:000169BA loc_169BA: ; CODE XREF: sub_16942+6Fj .text:000169BA call sub_12B96 .text:000169BF jmp short loc_16A37
Now we can agree that this is really useless code! So the idea is to move
up the following code, relocate the calls, and insert our ReleaseSemaphore
function code. Plenty of space for us, hoorray! So with adjustments
to acommodate the length of near jumps to the function exit point, our
code will finally look like this:
.text:00016942 ; int __stdcall Z3TbGptLoader__irpReadWrite(int, KIRQL NewIrql) .text:00016942 Z3TbGptLoader__irpReadWrite proc near ; DATA XREF: .rdata:0001897Co .text:00016942 ; .rdata:00018A1Co .text:00016942 .text:00016942 var_C = dword ptr -0Ch .text:00016942 var_8 = dword ptr -8 .text:00016942 var_1 = byte ptr -1 .text:00016942 arg_0 = dword ptr 8 .text:00016942 NewIrql = byte ptr 0Ch .text:00016942 .text:00016942 mov edi, edi .text:00016944 push ebp .text:00016945 mov ebp, esp .text:00016947 sub esp, 0Ch .text:0001694A push ebx .text:0001694B mov ebx, dword ptr [ebp+NewIrql] .text:0001694E push esi .text:0001694F mov esi, [ebx+60h] .text:00016952 cmp byte ptr [esi], 3 .text:00016955 push edi .text:00016956 setz [ebp+var_1] .text:0001695A mov edi, ecx .text:0001695C xor ecx, ecx .text:0001695E xor eax, eax .text:00016960 mov [ebp+var_C], ecx .text:00016963 cmp [edi+7Ch], ecx .text:00016966 jz short loc_1698B .text:00016968 mov ebx, [edi+7Ch] .text:0001696B push ecx .text:0001696C push ebx .text:0001696D push dword ptr [esi+10h] .text:00016970 push dword ptr [esi+0Ch] .text:00016973 call _alldiv .text:00016978 mov ecx, edx ; Semaphore .text:0001697A mov [ebp+var_C], eax .text:0001697D mov eax, [esi+4] .text:00016980 xor edx, edx .text:00016982 div ebx .text:00016984 mov ebx, dword ptr [ebp+NewIrql] .text:00016987 test ecx, ecx .text:00016989 jnz short loc_1699E .text:0001698B .text:0001698B loc_1698B: ; CODE XREF: Z3TbGptLoader__irpReadWrite+24j .text:0001698B xor edx, edx .text:0001698D add eax, [ebp+var_C] .text:00016990 adc edx, ecx .text:00016992 mov [ebp+var_8], edx .text:00016995 js short loc_169A7 .text:00016997 jg short loc_1699E .text:00016999 cmp eax, 0FFFFFFFFh .text:0001699C jbe short loc_169A7 .text:0001699E .text:0001699E loc_1699E: ; CODE XREF: Z3TbGptLoader__irpReadWrite+47j .text:0001699E ; Z3TbGptLoader__irpReadWrite+55j .text:0001699E cmp byte ptr [edi+0E2h], 0 .text:000169A5 jnz short loc_169B8 .text:000169A7 .text:000169A7 loc_169A7: ; CODE XREF: Z3TbGptLoader__irpReadWrite+53j .text:000169A7 ; Z3TbGptLoader__irpReadWrite+5Aj .text:000169A7 push ebx .text:000169A8 push [ebp+arg_0] .text:000169AB mov ecx, edi .text:000169AD call sub_12B96 .text:000169B2 nop .text:000169B3 nop .text:000169B4 nop .text:000169B5 nop .text:000169B6 jmp short loc_16A37 ; JMP here so that short JMP is enough .text:000169B8 ; --------------------------------------------------------------------------- .text:000169B8 .text:000169B8 loc_169B8: ; CODE XREF: Z3TbGptLoader__irpReadWrite+63j .text:000169B8 lea eax, [ebp+NewIrql] .text:000169BB push eax ; NewIrql .text:000169BC lea ecx, [edi+0FCh] .text:000169C2 call AddIRPToList .text:000169C7 test al, al .text:000169C9 jz short loc_169F4 .text:000169CB push ecx .text:000169CC lea ecx, [edi+20h] ; Tag .text:000169CF call AcquireRemoveLock .text:000169D4 or byte ptr [esi+3], 1 .text:000169D8 pop ecx .text:000169D9 push 0 ; int .text:000169DB call ReleaseSemaphore .text:000169E0 mov ecx, [ebp+arg_0] .text:000169E3 nop .text:000169E4 nop .text:000169E5 nop .text:000169E6 add edi, 11Ch .text:000169EC push edi .text:000169ED call sub_11B14 .text:000169F2 jmp short loc_16A37 .text:000169F4 ; --------------------------------------------------------------------------- .text:000169F4 .text:000169F4 loc_169F4: ; CODE XREF: Z3TbGptLoader__irpReadWrite+87j .text:000169F4 mov eax, dword_19024 .text:000169F9 mov esi, [eax] .text:000169FB mov [ebp+var_8], eax .text:000169FE cmp esi, eax .text:00016A00 jz short loc_16A21 .text:00016A02 .text:00016A02 loc_16A02: ; CODE XREF: Z3TbGptLoader__irpReadWrite+DDj .text:00016A02 mov ecx, [esi+0Ch] .text:00016A05 mov eax, [ecx] .text:00016A07 push 0 .text:00016A09 push 0 .text:00016A0B push offset aZ3tbgptloaderI ; "Z3TbGptLoader::irpReadWrite" .text:00016A10 push 1 .text:00016A12 push 0C0050007h .text:00016A17 call dword ptr [eax+8] .text:00016A1A mov esi, [esi] .text:00016A1C cmp esi, [ebp+var_8] .text:00016A1F jnz short loc_16A02 .text:00016A21 .text:00016A21 loc_16A21: ; CODE XREF: Z3TbGptLoader__irpReadWrite+BEj .text:00016A21 mov ecx, [ebp+arg_0] .text:00016A24 add edi, 8Ch .text:00016A2A push edi .text:00016A2B mov dword ptr [ebx+18h], 0C0000017h .text:00016A32 .text:00016A32 loc_16A32: .text:00016A32 call sub_11B14 .text:00016A37 .text:00016A37 loc_16A37: ; CODE XREF: Z3TbGptLoader__irpReadWrite+74j .text:00016A37 ; Z3TbGptLoader__irpReadWrite+B0j .text:00016A37 mov eax, [ebp+arg_0] .text:00016A3A pop edi .text:00016A3B pop esi .text:00016A3C pop ebx .text:00016A3D leave .text:00016A3E retn 8 .text:00016A3E Z3TbGptLoader__irpReadWrite endp
Finally, NOP out the calls to ReleaseSemaphore in AddIRPToList
(Remove the PUSH 0 and the CALL) and we’re finished patching it.
I made this modification and until now the driver seems to remain stable
(crossing fingers that it remains stable and I fixed the bug π )
Patch
As manually patching this is a real pain and I’m also not allowed to
redistribute a patched copy of the file. So I wrote a little patcher that
patches the driver accordingly. Just run it and
if it patched successfully, reboot the system to load the fixed version of the
driver.
Feel free to try it and if you are also suffering from this problem, you can
leave a comment if this actually fixes it for you too.
For those who use crappy Antivirus programs like Antivir, don’t get fooled by the generic Antivirus signature-match for compressed Executables XPACK.GEN, you can check with Virustotal.
If you have such an Antivirus program, use this build instead which is a larger executable but isn’t subject to false positives.
Comments
Alright!
The patcher working excellent!
No more BSoD from gtp_loader.sys on my computer.
Thank you very much for your help.
π
Thank you for this patch !
antivir says .exe is bad
Antivir is stupid π Their XPACK.Gen signature almost matches every packed or compressed executable, don’t rely on this signature. Here the reason behind it is that I merged Code and data section in executable so that the file gets shrinked in size.
Instead better check Virustotal analysis.
hello , help me please
I have the same problem
stop: 0x00000024 (0x001902fe, 0xb78c0d94, 0xb78c0a90, 0xf78c59e2)
gpt_lo~1.sys – address f78c59e2 base at
f78bf000, date stamp 4cf8f319
I need to patch gpt_loader.sys
Thank you very much for your hard work π
This patch has indeed solved the issue with gpt_loader.sys causing the computer to produce a bsod and then restart. I have tried to pressure the computer in a way that very often would cause it to restart due to the bug in the gpt_loader.sys. Even after I had installed this patch but before I had had the time to restart the computer, i got yet another bsod. But after the installation of the patch and the restart of the computer afterwards, I have not received a bsod due to the bug in the gpt_loader.sys, not even once.
Fantasic job, brilliant analysis.
After two days with the patched driver, no more BSOD. So far so good.
Just an interrogation : why not simply move the call to sub_166B2 (AddIRPToList) just after the ISL flags modification ?
Had same problem with Paragon HD Manager Profesional v12 10.1.19.16240 your patch seems to fix the problem. Brilliant analysis, it reminded me when I dissasembled Sinclair ZX81 rom… Paragon should fix their software…
Thanks!!!
when I added 3Tb in a SATA3 port, driver gave 0x0000007e at base B993EB6D @ B9938000 it does the same with patched/unpatched driver, apparently works ok in SATA2 ports, so it still has some limitations
Thanks for your replies, good to know that I’m not the only one who fnds the patch useful π
AnotherAnon: Because Flag should be only set if AddIRPToList succeeds. If there is no memory to allocate an IRP processing list entry for example, the code shouldn’t be executed but the else-Path with the memory error should be taken.
isidro: Maybe it is not compatible with your SATA3 driver, who knows? π You will need WinDbg to analyze this problem, but I suspect it will not be easily fixable, maybe it’s even a bug in the SATA-driver?
Seems not SATA3 related, same BSOD happened on old hardware. Seems related with having TWO 3Tb together. It did however worked on my new mother with H85 chipset. I only temporary add another 3Tb HD for backing up purposes.
Good to know, I’m now using this driver too and I was thinking about buying another 3TB, but if this ends with BSOD hell, I better take care.
Btw., I sometimes have system freezes somehow related to HDD access, but I never found out if this is related to Hardware or if this driver may be responsible. Did anybody else experience freezes (it often takes 1-2 months of uptime to happen)?
It usually starts with HDD led lighting for 2 seconds, system freezes for 2 sec and then the interval gets shorter and shorter until system locks up. But I never found any reference to this driver, so I still suspect that it may be a problem with my hardware.
Too bad that there are no other drivers out there than this one by Paragon.
Now my 2nd data drive is 3tb with GPT. No freezing issues, (just spin up delay from sleep sometimes). What worries me is after mirroring to another 3Tb, I had 3 or 4 corrupted files: With Total Commander I generate a file with full MD5 checksums of original, and same with backup, sort by name if necessary, and compare for any errors. I always do that and had no troubles with my 2Tbs backups. So be careful…
Hello dose,
sorry for my school english. Since long time i am using the paragon gpt loader and i found out some problems with this driver.
It’s a little tricky to get it work correctly. The IDE Mode is important.
But the really problem was, to get a GPT Loader that works. The standalone GPT Loader brings a BSOD by reboot after installing. So WinXP doesn’t starting in no way again by trying reboot. So you must reseting the system to state before you installed the Loader. Some other GPT Loader Versions in Paragon Software bundles will bring a WinXP Boot screen with slow sliders and nothing happens. No HD LED shows HD actions. So WinXP doesn’t start again. Installation by *.inf file doesn’t work too. Only the Paragon Disk Manager Suite Professional v12 works good for me.
But sometimes it cames a BSOD under WinXP. It seems ever happens, if i write and read files expensive on the 3TB drive. That’s seems exactly the problem, that you had, too. Your analyse here is great.
But i have a question. After extracting the GPT Files from all Paragon Products i found, it seems there are binary different versions for GPT_loader.sys but all called internal with v8.0.1.0!
– GPT Disk Manager – GPT Loader v10.0.16.12944
gpt_loader.sys= 68176 bytes
– Paragon Disk Manager v12 10.0.19.15177_000
gpt_loader.sys= 68176 bytes
gpt_loader.sys1= 51792 bytes
So the question is, is your patch working for all gpt_loader.sys file versions or only for special one?
I have another question for a second bug.
It seems, you know really good the code and understand them. So i hope, you could find a solution too. Paragon support don’t help.
So there is a memory bug in the gpt Loader. So long you are only copying file smaller then RAM in PC, you will nothing see. Only the HD LED on PC Case is working after the copy dialog is closed. That’s gives only a hint to this bug. So i can reproducing this bug on different PCs under WinXP. It doesn’t has to do with hardware or other System drivers. It only happens, if you copying Files or Folders greater then Memory from 3TB Disk to other target disk. But not happens between not MBR Disks. In Taskmanager you can see it under Systempower. The physical RAM Information shows the effect good.
If you are copying as example 20GB from 3TB GPT Harddisk to another 400GB MBR Disk, the process is at the beginning fast but the files aren’t writing direct to the other disk. Before writing data, the systemcache will be grow up to 2,3GB and the free Ram will be small to 4MB at last. So it is clear, the GPT Loader don’t write direct to disk. It caches the files into the RAM before writing them. By small files, you feel nothing. The PC speed doesn’t change. But if you transfer 6GB and more as your PC Ram has, the memory runs full and winXP slows down or freezes for every file to write.
I think, this paragon behavior for filecopy brings different problems. You can’t use move files, because by using the move file command between different HDs (one of them 3TB) than Datas lost, if PC lost the power, because no power so no cached files in RAM anymore and the windows move command deleted the files on sourcedisk before the writing of the cached files are complete. The transfer dialog is closed before the real data transfer from RAM to disk is complete. You think, it is all transfered but the HD LED on PC case shows by lighting, the hd is working and the PC keeps slow for some minutes, because in background the writing proecess runs and completes the last files from memorycache to disk. You better don’t shut down the PC in this moment, because the copy process isn’t ready. That’s really stupid behavior.
But more silly effect is, that the free memory sinks down to 4MB by copy datas greater 4GB. The systemcache or filecache will run full. And if only 4mb for winXP Kernel keeps left, the system can’t open new programs or switch between programs. All hangs. Only after the copy command is complete or will be abort by user, the system will be reach normal speed and handling again. But only, if the last Cached files from RAM after copy abort will be write to disk complete. So the copy dialog is closed but in background the writing process isn’t complete and needs some time. You can see this ever, the system will be slow and after every file is write, the system is short normal reaction. If the first cached files are complete on disk, the gpt Loader gives the RAM free again but using then the RAM again for the next files to cache by copy process. The Systemcache doesn’t go down. It keeps by 2,3GB. So while copy the files in RAM, the system slows down if only 4MB keeps at last. That’s awefull, if you will copy folders with much great files.
If you only fill the 3TB HD over month with small files, it’s no problem. The PC doesn’t slow down. 100MB here, 2GB there and so on. That’s no problem. 4GB one time, you feel short the PC is slow, but after seconds or one minute all is normal. So you don’t think, it could have to do with copy process by gpt Loader.
But if you will copy a complete folder with 400GB to other disk, you can do this only in the night or in time you don’t need the PC. Working with PC is impossible.
And this is no problem with hardware. It is the same on old PC or on ASROCK FM2A88M-HD+ with AMD A10-7800 APU under XP. It is a bug by Paragon GPT Loader. It uses the scsi port but i don’t understand, why they reading/ caching the files complete in RAM for writing.
I think, it will be nice, if the free PC RAM/Memory will not used complete by GPT Loader, if you are starting a file copy. There must be a limit. So as example there keep 300MB free for Winxp/other Programs and not only 4MB System kernel. Then the system will not freezes because there is some free RAM for other programs.
On other side, it will be nice, if the GPT Loader don’t cache files in ram. Why GPT Loader can’t writing direct from disk to disk like normal Controller direct without caching the files in RAM? If you copy files between other MBR 2TB HD without using the GPT Loader (not 2TB+ GPT Disks), the free RAM don’t changed and the Systemcache don’T grow up, while file copy runs. So the problem happens only, if a Harddisk uses GPT Loader.
Is it possible, you can limit the Cache function in GPT Loader, so there keeps enough free RAM and the System doesn’t slow down or freezes so long the copy process runs?
Is it possible, change GPT Loader so, that the copy dialog only close them self, after the cached files are writed really complete from RAM on disk?
Is it possible, change GPT loader to write Files direct to disk like normal copy mode and don’t use the RAM for caching files?
The RAM Caching Bug is really awefull. So i hope, you can analyse them.
Hi Atlan, your english is difficult to undestand. Correct GPT_LOADER.SYS size is 51792 bytes. I have no troubles copying or moving big files. Try using Total Commander or another program for copying, I’m almost sure cache isn’t managed by GPTLOADER.
Other Program is the same result. If your winXP has 4GB RAM and you are copy a folder with files greater than RAM like 20GB, you can see the effect in Taskmanager. In the beginning of the copy process the files cached in RAM so long, if there is at last only 4MB free RAM available. It looks, the copy process is very fast but then it slow down the machine. There keeps only enough free RAM 4MB for the Windows core files. But this effect comes only, if i copy some files from the 3TB GTP Harddisk to other targets. That means, there is no change of RAM usage, if i copy files from a not 3TB GPT Harddisk to another not 3TB GPT Harddisk. So the file Transfer with standard Dual-Channel Controller between MBR Harddisk have no effect on RAM usage. So it must have to do with GPT Loader. I could reproduce this effect on different WinXP PCs with different 3TB GPT Harddisk.
I thought first, it has to do with the registry key Largesystemcache but i have not set this tuning key or other. And all Harddisk works good. Under Windows Vista or 7 the 3TB GPT Harddisk doesn’t show this effect with MS Standard driver.
The only difference is, that under WinXP i need the GPT Loader and it seems, the GPT Loader uses extremly the filecache/Systemcache by copy process.
Sorry Atlan, created a 20gb file, copied from 2Tb to 3Tb GPT, winxp prof, at the same time I’m capturing tennis match with VirtualDub, CPU usage is under 35%, ram usage is 400MB. File copied with Windows Explorer in 6 minutes. No drop frames on capture…
You may try Total Commander, it has advanced options to set the size of cache on big/small file copies.
I have two different versions of GPTLOADER, one came with Hitachi drives, both are same size and both are patcheble. I’m using hitachi version now. I can send it if you want. My mail is isidrococo at gmail.
After your answere, i made some tests. You are right and i am too. It isn’t so simple, i thought. How full or empty is your Harddisk? You have one Partition on 3TB HD?
My 3TB Harddisk is one partition of 2794 GB and i used them for 2 years only for data backup.
But in the last 3 month, i copying much files from my 3TB to 2 x 2TB HD and compare them binary before i delete them on 3TB. From 2,6TB data keeps there only at last 1,2TB left on 3TB Disk. At this time I don’t check, where these files located on disk.
After your response, i tried to copy 8GB MP3 Folder with 8000 files and a DVD folder with 6GB (5x1GB files) to 3TB Disk in one copy process and back to 2TB Harddisk. I want show, what happens by many small files and by bigger files in one copy process with 14GB.
The copy process seems to keep in the beginning normal by mp3 folder but the available RAM falls down from 2,3GB to 1,8GB and later by DVD Files to 600MB. This shouldn’t happen but the available RAM keeps over 4MB, so the PC don’t slow down. I thought, the big DVD files with 6GB should reduce the available RAM at last to 4MB. That’s not happen.
That’s not, what i saw in the last days before. So i check the location of files on Disk. Windows defrag tool shows me now, most of these files are placed on the end of Harddiskspace. So over the 2TB limit.
I tried again, to copy some of the last 1,2TB files from 3TB to other Harddisk. It is a folder of 22GB with 250 Files. The most of these files are 95MB big. The copy process slow down the machine while it fills the systemcache and reduce the available RAM to 4MB. That’s exactly the bad effect, i mean and saw the last days. After the copy is complete, i beginn to copy the folder back from the other Harddisk to the 3TB in separate folder. But the copy Process is normal. No slow down effect or extremly RAM usage. The available RAM keeps on 2,3GB. So I copying this new copy of folder again from 3TB to other Harddisk. The copy process isn’t slow down the PC. I do so 3 Times. Then i can see, there is some effect. The RAM goes down to 1,3GB but not deeper. Then i begin to fill the 3TB Harddisk with more copies of the 22GB Folder and after 3 copies i can see no problem. But than i copy the last test folder back to other Harddisk from the 3TB and the process sems normal in the beginning. But after 6minutes the available RAM reduces from 2,3GB to 4MB and the copy process slow down the machine and the rest of copy time goes from 2minutes to 111minutes. The copy process ends but the HD LED on PC case shows the Harddisk isn’t ready with the work. The available RAM goes only slowly up to 2,3GB.
So it seems, that this effect have to do, with the position on Harddiskspace and the copy direction. Writing to 3TB Disk isn’t so extremly a problem. Copy the data back to other disk is the problem, if the files place on Diskspace near 2TB limit.
So you doesn’t see this effect, if you never fill the 3TB Harddisk complete, i think. But the GPT Loader uses in some situation the RAM as Filecache and slow down the PC. But not ever.
The CPU Usage isn’t important by copy some files with GPT-Loader. I have 4 cores CPU and they are all by 0-1% while the copy transfer is running. The PC don’t slows down by CPU Usage. It slows down and freezes, if there keeps only 4MB free RAM available.
I ask my self, what happens, if i use the 3TB not with one Partition. In many paragon answeres, they said ever that you should made 2 Partitions under 2TB, because one partition don’t work. But i know, it works. No data is corrupted or lost. But would reduce 2 Partitions this RAM effect?
I also experienced this annoying behaviour with this driver, i.e. when copying around disk images. The system slowed down to a creep. I don’t think that the read/write operations are cached, though. The constant HDD access after completing the operation most likely is related to the paging activity of the system swapping back stuff from paging file to RAM.
I also don’t know if caching is the issue. The System Cache also increases when you do normal file copy operations on disks that don’t use GPT loader. Cache is managed by the NT Cache Manager which sits on top and doesn’t really get directly accessed by the driver from what I know. As cache memory aprox. stays the same but physical memory gets reclaimed after read operation, I’m not sure if the amount of memory allocated on read from GPT drive really relates to cache. On the other hand, when doing slow reads i.e. like playing a movie, the loss in physical memory approx. ocrrelates to the growth of the System Cache. But as System cache has a limit (i.e. here it is limited with 1GB) and physical memory still vanishes when cache is full, it wouldn’t make any sense that all memory is attributed to cache.
s you have noticed, something in the GPT loader driver causes it to consume insane amounts of physical memory during read operations (as you correctly found out, it doesn’t occur on write operations). The allocated memory very slowly gets reclaimed after operation finished at least, otherwise this leak would soon kill the system, I guess.
I wonder what is causing this. First thing to suspect is the Pool (the driver’s heap), but this doesn’t seem to be the case here, because pool memory is limited (i.e. on my system it cannot exceed 360MB Paged Pool and 256MB nonpaged pool) and Process Explorer shows that there is no significant increase in Pool memory usage. It only shows a big growth in physical memory usage. So PoolMon debugging also won’t help us here. The other memory allocating call I see in the driver is MmMapLockedPagesSpecifyCache() which is called in processIrp. But this should normally be freed by the IO manager, so I also don’t know if this is the cause for the leak. Currently I’m a bit clueless. I don’t want to mess around on my production machine risking data loss.
I’ve documented the copy operation now.
The Problem happens not every time. Only by files, they stored behind the 2TB disc space area.
The files are cached only by read process in this area.
I made a DOC with pictures, so everybody can see, what happens exactly.
http://www.file-upload.net/download-10690739/GPT-Memory-Leak.doc.html
@dose
i can reproducing this effect ever i want, because i know the folders with the files they are producing this memory leak effect. I saved all data from my System to another Harddisc. I can put them away from system, so i have nothing to loose. I let the rar files on my 3TB Harddisc, so you know, how to proof your patches. Or install the software, that you need for your work. If you want, you could make test on my machine with teamviewer. If this helps you. At this time this desktop pc isn’t my production machine. It’s a offer from me to you. I hope for a solution. But you must know, it is a german win XP. Other languages aren’t a problem for me. I worked on chinese windows systems but i can’t chinese. You must know only, the most functions under windows have ever the same menu position. Let me know, if you want try so.
Hi Atlan,
I just released a patch for your problem (newest blog post), please let me know if it works for you. π
I test it out and can say, it works. Thanks. π
Your patcher is a godsend! Thank you so much, no BSODs anymore!
I get a 7E BSOD by GPT-Loader.sys. The funny think is, that there is no GPT formated Harddisk or any other Harddisk above 2TB working in PC.
The BSOD happens, as i shutdown the System in Hibernate mode. So System is complete powerless. At this time i connected 2x 2TB Harddisk and power in the System. After wakeup from hibernate the Desktop shows and the BSOD by GPT-Loader happens.
Normally the System makes a Hardware Update check and connected the Harddisks. But at this time the gptloader.sys seems to do something. But gptloader isn’t needed by this harddrives. No one using gpt or was above 2TB.
I think, this is a really special BSOD and there will no solution for this, because nobody doing like me and build in some HDs in Hibernate mode.
I guess it’s the same problem like the BSOD that you get when you try to remove the IDE-channel in Device manager (which i.e. is needed if some drive was reset to PIO from DMA mode). My guess is that both problems are due to bad PNP-Management done by the driver. But I didn’t analyze these errors, because I consider them only a little annoyance which is not, unlike the other 2 problems that I patched, preventing normal operation as it only happens in certain rare cases.
i thougt ever, the gptloader will only load for gpt formated Partition or Harddisk above 2TB. But what you write, sounds right. It must have to do with PnP-Management. IDE Devices don’t like to take off them or connect them by running system. But in powerless mode it goes. There was most times no problem to do so. So i was suprised as the gptloader shows the 7E message, because there wasn’t any Harddisk connected to the system at this time which needs the gptloader.sys. But gptloader must analyze them, after i connect them. So it isn’t important, if there is some gpt Partition on Harddisk or with Space greater than 2TB. The BSOD 7E happens only first time yesterday. By other times no error happens. So it is like you write, it is only a little annoyance sometimes. Nothing is perfect.
>But gptloader isnβt needed by this harddrives.
Installing the driver also installs gpt_loader as upper filter for ALL the HDDs.
You may renew driver (choosing common windows driver) for all the <2T HDDs so they wouldn't depend on gpt_loader anymore.
The smart way to install gpt_loader is to install it as upper filter ONLY to the selected HDD.
If you are using (see in device manager) common windows driver, you controller is on ide mode, your disk drivers are only "standart" partmgr.sys and disk.sys, then you may use this way. Place the text below (starting from "[Version]") as somename.inf in a folder with (patched) gpt_loader.sys /51792 bytes/, then select the proper disk from the device manager, then renew driver manually using option "install from disk" and choose the driver folder with somename.inf and gpt_loader.sys.
This will install gpt_loader ONLY to selected HDD so you'll be able to do with other HDDs whatever you want.
This my inf adds gpt_loader service as upper filter to standard windows disk driver (installation includes windows folder disk.inf). For my 3TB WD Green HDD this way works fine on WinXPsp3.
[Version]
Signature="$Windows NT$"
Provider=%Paragon%
Class = DiskDrive
ClassGuid = {4D36E967-E325-11CE-BFC1-08002BE10318}
DriverVer=11/22/2009,8.0.1.0
DriverPackageType = ClassFilter
[DestinationDirs]
DefaultDestDir = 12
[Manufacturer]
%Paragon% = Paragon.Mfg,
[Paragon.Mfg]
%Paragon% = gpt_loader
[gpt_loader]
; perform port related actions from disk.inf
Include=disk.inf
Needs=STANDARD_Inst
; Copy the driver over
CopyFiles=gpt_loader.CopyFiles
; File sections
[gpt_loader.CopyFiles]
gpt_loader.sys
; Service Installation
[gpt_loader.Services]
AddService = gpt_loader, , gpt_loader_Service_Inst
; Install the driver from disk.inf
Include=disk.inf
Needs=STANDARD_Inst.Services
[gpt_loader_Service_Inst]
DisplayName = %gpt_loader.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 0 ; SERVICE_ERROR_IGNORE
LoadOrderGroup = "PnP Filter"
ServiceBinary = %12%\gpt_loader.sys
AddReg = clasfilt_EventLog_AddReg
[clasfilt_EventLog_AddReg]
HKLM, System\CurrentControlSet\Services\Eventlog\system\gpt_loader,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%\System32\drivers\gpt_loader.sys;%%SystemRoot%%\System32\IoLogMsg.dll"
HKLM, System\CurrentControlSet\Services\Eventlog\system\gpt_loader,TypesSupported, %REG_DWORD%, 7
HKLM,"SYSTEM\CurrentControlSet\Services\gpt_loader","Start",65537,3
[gpt_loader.HW]
; Add the device upper filter
AddReg = gpt_loader.HW.AddReg
; run the directives need by the port driver
Include=disk.inf
Needs=STANDARD_Inst.HW
[gpt_loader.HW.AddReg]
HKR,,"UpperFilters",0x00010000,"gpt_loader"
HKLM,"System\CurrentControlSet\Services\gpt_loader","VIDS",1,0E,DA
[SourceDisksNames]
1 = %DiskId1%,,,
[SourceDisksFiles]
gpt_loader.sys = 1,,
[Strings]
Paragon = "Paragon and Co BIG HDD"
gpt_loader.SvcDesc="GUID Partition table support driver"
DiskId1 = "3Tb HDD disk driver"
REG_SZ = 0x00000000
REG_MULTI_SZ = 0x00010000
REG_EXPAND_SZ = 0x00020000
REG_BINARY = 0x00000001
REG_DWORD = 0x00010001
SERVICEROOT = "System\CurrentControlSet\Services"
After i patch it i keep getting a BSOD: http://i.imgur.com/U8tmNZG.jpg
If i don’t run the patch and use the stock gpt_loader.sys file and rename it so Windows can’t find it, i get the same error rather than Windows starting and simply preventing my 4tb drive from working.
I have dual boot so i load Windows 7 and delete the patched file and restore the original file to reload Windows XP.
Any idea what i’m doing wrong? I’m using Paragon GPT Disk Manager, also tried Hitachi drivers and Paragon Hard Disk Manager 15 and keep getting BSOD when i patch.
Also, @DCT, would that work in AHCI mode or just IDE mode?
What an amazing piece of reverse engineering! After years of agony, finally a solution! I just checked my notes, and I have saved over
150 BSOD err msgs from 2011 to 2015 on my XP, all BCP codes related to this issue. Have been running my system with your patch (incl. “revisited”) for 5 months now, and not a single BSOD anymore. I would like to shake your hand, excellent work, my sincere gratitude!
Great analysis, am humbled by your skillset, superb patch, a gem. Thanks for sharing this, needless to say – most highly recommended!
To user “DCT”:
According to your description:
“[gpt_loader.HW.AddReg]
HKR,,”UpperFilters”,0x00010000,”gpt_loader””
there is a mistake because this regwrite command overwrites the existing value “PartMgr” which is already stored in “UpperFilters”. You have to APPEND the “gpt_loader” value.
Example:
[gpt_loader.HW.AddReg]
HKR,,”UpperFilters”,0x00010008,”gpt_loader”
Is there any possibility to get the gpt driver to work with an external USB HDD drive? I already hooked up the driver to the USB Storage UpperFilters ({71A27CDD-812A-11D0-BEC7-08002BE2092F}) but no success.
A general question: Do I need the AHCI S-ATA mode or the IDE mode to get the gpt driver to work?
satmonk: Never tried with external HDDs.
The driver itself usess ATA-Commands (and talks to ATAPI.SYS), so I don’t think it would be able to deal with AHCI. I’m using all my drives in IDE mode.
it uses the ATAPI.SYS, OK, that’s why it cannot work with external USB drives (they don’t make use of the ATAPI.SYS driver). So it needs an ATA emulator driver for USB (if such a driver exist…). I will try the UniATA driver, probably a solution to get AHCI to work. (UniATA: one driver file for both systems -> ATA and AHCI)
Regards,
i have a seagate 5 TB divide with 2 partitions 2.27 and 2.26 TB
never had a BSOD not that i remember but system comes useless time to time after i copy larger
files like 2 GB etc, disk takes longer to finish the copy process, while copying the system became
slow (unstable) and almost unresponsable, i have attached another HD of 2 TB and when i copy from
there to the 5 TB (one of the partition) system became unstable, disk stayed like there’s constant HD activity, i have used your patch and says patch sucessfully, i tried copying a big file from same disk partition to test and the problem did not occur, so there’s has to be some other leak missing or something else
i have AHCI activated in BIOS, should i disable?? i activated because my boot disk is an SSD and it’s recommend to activate this option, also i’m using the Paragon GPT Loader v10.0.16.12944,
should i use other version or what i’m missing ??
please! ideas and help is welcome!!
My Best Regards
after i copied a 1.5 GB file from same disk partition to same folder, after some minutes disk stay like there’s constant activity and i’m doing nothing, i have no proccess running or antivirus, if i wait longer i believe the same problem will occur and forcely will have to reboot, system is unstable, so my guess is the problem occur either writing to disk as well, not only reading, any ideas??
i will disable AHCI and report back, please, advices and help are welcome!
Have you read
http://hardwarefetish.com/612-gpt_loader-sys-revisited-file-read-problem ?
Sounds like this problem to me.
with autoruns (sysinternals) i disabled from registry the iastor intel driver and related service, restarted and disabled from Bios the AHCI feature
so far everything OK, i copied a 4 GB file from the 2 TB drive into the 5 TB, copy process was fast and not constant HD activity after doing, copied 3 GB mkv from the 5 TB disk into the one with 2 TB, copied sucessful and not constant HD activity neither BSOD.
i will be testing and report if anything strange occur, i guess using gpt loader driver and AHCI is not compatible at all even using the patch, so i recomend using IDE enhanced mode if you use WInXP with a disk of 3 TB+
the only inconvenient now, is that SSD became slow while booting, i see now why is important having AHCI enabled with solid drives.
any advices are welcome.
My Best Regards
@dose
by any chance could you check if you have any left for iostor drivers (AHCI) drivers, running in background/registry?
i really apreciate all your hard work and for making available these information, i’m sure you know what you’re doing here, that’s why since i first entered this website and saw your tuto about this, instantly i knew you’re the man !!
if issue comes again i will for sure try your second patch. and will re activate AHCI to check what happends, i need it for my SSD boot disk, without it the performance is reduced, any ideas??
Thanks again for everything.
My Best Regards
@Rickz As you can already read in the comments, I stated that the driver uses ATAPI commands, no AHCI involved.
On my machine, BIOS also runs in IDE compatibility mode, no AHCI involved, that’s how it works…
@dose
i don’t think it has to do with AHCI since other partition it’s working, the only difference is it has more than 1 TB available (free), neither the disk has damaged sector, this disk is brand new.
i will be back to IDE mode and test again, will reply back later
Regards
@dose Well, your work is amazing!
I had those BSOD for many years and didn’t find anything related to solve it.
newer versions on that drive are supplied in other Paragon products, but I didn’t succeed to test them.
My HD is partitioned in 2 partitions where the first one do not exceed the 2TB limit, its only the second one which occupied the left over.
since I realize that every long operation (read or write) on the second one continuously generate BSOD, therefore I avoid to access it under XP. but even so, some times for no reason that BSOD appeared.
I hope your solution will eliminate it, already made few tasks to test it, until now its looks promised. Thank you very much!
Only two questions / request, just to be sure. since I noticed you have made another patch and also I got an already patched file which is different then the resulting file (while using patches posted here), is it possible you provide the hash for the 2 files generated after applying the two patches. in other words what is the correct hash for the patched files after patching it once & twice.
My hashes are as below:
1. Original untouched gpt_loader.sys
File: gpt_loader.sys.bak
MD5: 2234a9ba20e6a5d4d6404c499e8438a2
SHA-1: a69718cdd23ffb4aca6e67a6906569c0c2084c10
2. First patch (the one posted here) apply to gpt_loader.sys
File: gpt_loader.sys.bak2
MD5: de4f3b8b117dc8fe1b7b995699e6dd0b
SHA-1: 762b9eef6986fa352f537fb106997928d41f3875
3. Second patch (from the other post at 612-gpt_loader-sys) apply to gpt_loader.sys
File: gpt_loader.sys
MD5: fcf46d5eb9e1698ef5760fe48864b64b
SHA-1: 490debe09a5589025b5035b1971ae28c1702cd32
4. unofficial already patched gpt_loader.sys which claim to have used your patches provided in WinXP build called “Integral Edition” (suppose to support all modern HW) its also bigger in size 50.7kb (instead of 50.5).
File: gpt_loader.sys
MD5: 9c70bc2909911914164cbf3d15813df2
SHA-1: 7d29c6dd726b5239a9267e749d55a6ec345da2a5
BTW, a different solution was posted at Fernando’s forum (https://www.win-raid.com/t4035f45-Windows-XP-Bit-and-Server-Bit-on-Modern-Hardware-296.html#msg110653), its documents says that those patches do not fix file system corruption problems, therefore he suggest Hybrid MBR. upload.ee/files/11625492/WinXP_GPT.zip.html
do you know this solution? can you confirm that there is still a problem even using your fix?
@meni @dose
in original installer (Paragon-197-PEE_WinInstallSNU_10.0.16.12944)
exist two drivers, in XP pro is installed the one has 50.5 KB on disk, i uploaded both(unmodified) here:
mediafire.com/file/1hy004szy9qev87/gpt_loader.zip/file
i guess the bigger drivers belong to other OS version..
there is other vrsion i guess with shorter size which virtual windows (MiniXP) uses(extracted from DLC boot 2019) this is similar to hiren’s boot, i’m not sure if it’s patched i believed i replaced for testing and it work, just when back to original patched by @dose just in case, i wish to use AHCI for my ssd samsung which runs faster.. this is the only limitation i have found so far, it’s been working writting/reading fine.. i will apply last second patch
file from minixp: mediafire.com/file/oejjs5dxqe3uyvd/gpt_loader-from_dlcboot_2019.zip/file
@Rickz: The bigger file is 64bit version, the smaller is 32bit version.
I patched 32bit version, wo is using XP64 anyway..?
@dose
Regards,
by the way, do you know if this driver has something related to Physical Address Extension (PAE) on windows XP ?
after increasing ram one of the partitions of the 5 TB disk some data reads as corrupts, most videos and rar/zip files looks damaged, when i reboot without forcig PAE everything is OK, this is very strange, so far only happends with one partition,
maybe it’s because has only 80 GB left ? the other partion has 1 TB left, any way, coyping files from 1 TB partition to
another HD , sometimes data copied is filled with 000000, even short exe file (155 KB)
this is my boot.ini config:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Windows XP (PAE Test)” /noexecute=optin /fastdetect /HAL=halpae.dll /KERNEL=ntkrpae.exe
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Microsoft Windows XP Professional” /fastdetect
btw disk(0) is another disk with windows installed,normal NTFS without gpt
any ideas what could be wrong ?
PAE for XP source info: https://forums.mydigitallife.net/threads/drivers-and-tools-to-run-windows-xp-on-newer-hardware.81607/
My Best Regards
interesting article installing gpt support using wk3 drivers: https://article-pchome-net.translate.goog/content-1324506-all.html?_x_tr_sch=http&_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp
Hello!
why can’t see previous comments?? 51 comments erased? π
Regards,
about installing disk.sys driver from win2k3, only i recomend to take this adventure if disk is new or safe to format/delete, i tried this with already formated/filled with data and one of the partition is not recognized and the other has errors, don’t do chkdsk on any of the present partitions or will possibly damage your data… just recorver previos backup of the drivers/reboot and you’ll be ok, will have to do it again with a drive that i can format and test this…if you already have data, backup everything before using this method…better if testing with empty this….
Trackbacks