Skip to content

Instantly share code, notes, and snippets.

@rajkosto
Last active February 10, 2025 21:12
Show Gist options
  • Save rajkosto/6bb60346d8a7f7f4e21566618e44020a to your computer and use it in GitHub Desktop.
Save rajkosto/6bb60346d8a7f7f4e21566618e44020a to your computer and use it in GitHub Desktop.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Shlobj.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
bool replaceAllInFile(const TCHAR* filePath)
{
FILE* file = _wfopen(filePath,TEXT("rb"));
if (!file)
{
puts("Error opening file for reading: ");
_putws(filePath);
puts("\n");
return false;
}
else
{
puts("Opened file for reading: ");
_putws(filePath);
puts("\n");
}
//Read file content into memory
fseek(file,0,SEEK_END);
size_t fileSize = ftell(file);
fseek(file,0,SEEK_SET);
//Ensure file size is valid before allocating buffer
if (fileSize <= 0)
{
printf("File is empty or error reading the file size.\n");
fclose(file);
return false;
}
char* buffer = (char*)calloc(fileSize+50,1); //+50 to prevent reading past end of buffer
if (!buffer)
{
printf("Memory allocation of in buffer of %zu bytes failed\n",fileSize+50);
fclose(file);
return false;
}
size_t bytesRead = fread(buffer,1,fileSize,file);
if (bytesRead != fileSize)
{
printf("Error reading the file. Bytes read: %zu, Expected: %zu\n",bytesRead,fileSize);
free(buffer);
fclose(file);
return false;
}
buffer[fileSize] = 0;
fclose(file);
file = NULL;
size_t outSize = fileSize;
char* outBuffer = (char*)malloc(outSize);
if (!outBuffer)
{
printf("Memory allocation of out buffer of %zu bytes failed\n",outSize);
free(buffer);
return false;
}
static const char search1[] = "\"Disable_FG_Override\":true";
static const char replace1[] = "\"Disable_FG_Override\":false";
static const char search2[] = "\"Disable_RR_Override\":true";
static const char replace2[] = "\"Disable_RR_Override\":false";
static const char search3[] = "\"Disable_SR_Override\":true";
static const char replace3[] = "\"Disable_SR_Override\":false";
static const char search4[] = "\"Disable_RR_Model_Override\":true";
static const char replace4[] = "\"Disable_RR_Model_Override\":false";
static const char search5[] = "\"Disable_SR_Model_Override\":true";
static const char replace5[] = "\"Disable_SR_Model_Override\":false";
static const char search6[] = "<Disable_FG_Override>1</Disable_FG_Override>";
static const char replace6[] = "<Disable_FG_Override>0</Disable_FG_Override>";
static const char search7[] = "<Disable_RR_Model_Override>1</Disable_RR_Model_Override>";
static const char replace7[] = "<Disable_RR_Model_Override>0</Disable_RR_Model_Override>";
static const char search8[] = "<Disable_RR_Override>1</Disable_RR_Override>";
static const char replace8[] = "<Disable_RR_Override>0</Disable_RR_Override>";
static const char search9[] = "<Disable_SR_Model_Override>1</Disable_SR_Model_Override>";
static const char replace9[] = "<Disable_SR_Model_Override>0</Disable_SR_Model_Override>";
static const char searchA[] = "<Disable_SR_Override>1</Disable_SR_Override>";
static const char replaceA[] = "<Disable_SR_Override>0</Disable_SR_Override>";
size_t outN = 0;
for (size_t i=0; i<fileSize; i++)
{
size_t searchLen = 1;
size_t replaceLen = 1;
const char* replaceSrc = &buffer[i];
if (!_strnicmp(replaceSrc,search1,sizeof(search1)-1))
{
searchLen = sizeof(search1)-1;
replaceSrc = replace1;
replaceLen = sizeof(replace1)-1;
}
else if (!_strnicmp(replaceSrc,search2,sizeof(search2)-1))
{
searchLen = sizeof(search2)-1;
replaceSrc = replace2;
replaceLen = sizeof(replace2)-1;
}
else if (!_strnicmp(replaceSrc,search3,sizeof(search3)-1))
{
searchLen = sizeof(search3)-1;
replaceSrc = replace3;
replaceLen = sizeof(replace3)-1;
}
else if (!_strnicmp(replaceSrc,search4,sizeof(search4)-1))
{
searchLen = sizeof(search4)-1;
replaceSrc = replace4;
replaceLen = sizeof(replace4)-1;
}
else if (!_strnicmp(replaceSrc,search5,sizeof(search5)-1))
{
searchLen = sizeof(search5)-1;
replaceSrc = replace5;
replaceLen = sizeof(replace5)-1;
}
else if (!_strnicmp(replaceSrc,search6,sizeof(search6)-1))
{
searchLen = sizeof(search6)-1;
replaceSrc = replace6;
replaceLen = sizeof(replace6)-1;
}
else if (!_strnicmp(replaceSrc,search7,sizeof(search7)-1))
{
searchLen = sizeof(search7)-1;
replaceSrc = replace7;
replaceLen = sizeof(replace7)-1;
}
else if (!_strnicmp(replaceSrc,search8,sizeof(search8)-1))
{
searchLen = sizeof(search8)-1;
replaceSrc = replace8;
replaceLen = sizeof(replace8)-1;
}
else if (!_strnicmp(replaceSrc,search9,sizeof(search9)-1))
{
searchLen = sizeof(search9)-1;
replaceSrc = replace9;
replaceLen = sizeof(replace9)-1;
}
else if (!_strnicmp(replaceSrc,searchA,sizeof(searchA)-1))
{
searchLen = sizeof(searchA)-1;
replaceSrc = replaceA;
replaceLen = sizeof(replaceA)-1;
}
if (replaceLen != searchLen)
{
outSize += replaceLen-searchLen;
outBuffer = (char*)realloc(outBuffer,outSize);
if (!outBuffer)
{
printf("Memory allocation of new out buffer of %zu bytes failed\n",outSize);
free(buffer);
return false;
}
}
memcpy(&outBuffer[outN],replaceSrc,replaceLen);
outN += replaceLen;
i += searchLen-1;
}
free(buffer);
buffer = NULL;
//Write the new buffer back to the file
file = _wfopen(filePath,TEXT("wb"));
if (!file)
{
puts("Error opening file for writing: ");
_putws(filePath);
puts("\n");
free(outBuffer);
return false;
}
size_t bytesWritten = fwrite(outBuffer,1,outSize,file);
free(outBuffer);
fclose(file);
if (bytesWritten != outSize)
{
printf("Error writing to file. Bytes written: %zu, Expected: %zu\n",bytesWritten,outSize);
return false;
}
printf("File updated successfully. Old size: %zu, new size: %zu\n",fileSize,outSize);
return true;
}
bool setFileReadOnly(const TCHAR* filePath, bool shouldBeReadOnly)
{
DWORD oldAttrs = GetFileAttributes(filePath);
if (oldAttrs == INVALID_FILE_ATTRIBUTES)
{
puts("Error getting file attributes for : ");
_putws(filePath);
puts("\n");
return false;
}
DWORD newAttrs = oldAttrs;
if (shouldBeReadOnly)
newAttrs |= FILE_ATTRIBUTE_READONLY;
else
newAttrs &= ~FILE_ATTRIBUTE_READONLY;
if (newAttrs == oldAttrs)
return true;
if (!SetFileAttributes(filePath,newAttrs))
{
puts("Error setting file attributes for : ");
_putws(filePath);
puts("\n");
return false;
}
return true;
}
bool restartService(const char* serviceName)
{
//Prepare command to stop and start the service
char command[256] = {};
snprintf(command, sizeof(command), "net stop %s && net start %s",serviceName,serviceName);
printf("Attempting to restart service: %s\n", serviceName);
//Execute the command
int result = system(command);
if (result == 0)
{
printf("Service %s restarted successfully.\n", serviceName);
return true;
}
else
{
printf("Failed to restart service %s. Command result: %d\n", serviceName, result);
return false;
}
}
int main()
{
TCHAR localAppDataPath[1024] = {};
if (!SUCCEEDED(SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,localAppDataPath)))
{
puts("Error getting local app data folder path\n");
return 2;
}
static const TCHAR TargetDbFileSuffix[] = TEXT("/NVIDIA Corporation/NVIDIA app/NvBackend/ApplicationOntology/data/fingerprint.db");
{
TCHAR fingerprintDbPath[1024];
wcscpy(fingerprintDbPath,localAppDataPath);
wcscpy(&fingerprintDbPath[wcslen(fingerprintDbPath)],TargetDbFileSuffix);
if (!setFileReadOnly(fingerprintDbPath,false))
goto onError;
if (!replaceAllInFile(fingerprintDbPath))
goto onError;
if (!setFileReadOnly(fingerprintDbPath,true))
goto onError;
}
static const TCHAR TargetJsonFileSuffix[] = TEXT("/NVIDIA Corporation/NVIDIA app/NvBackend/ApplicationStorage.json");
{
TCHAR jsonPath[1024];
wcscpy(jsonPath,localAppDataPath);
wcscpy(&jsonPath[wcslen(jsonPath)],TargetJsonFileSuffix);
if (!setFileReadOnly(jsonPath,false))
goto onError;
if (!replaceAllInFile(jsonPath))
goto onError;
}
//Services to restart
static const char SERVICE_1[] = "NvContainerLocalSystem";
static const char SERVICE_2[] = "NVDisplay.ContainerLocalSystem";
printf("Restarting NVIDIA services...\n");
restartService(SERVICE_1);
restartService(SERVICE_2);
system("pause");
return 0;
onError:
system("pause");
return 1;
}
@rajkosto
Copy link
Author

rajkosto commented Feb 1, 2025

Statically linked compiled version available at: https://files.sshnuke.net/SearchReplaceNvidiaApp.exe

@rajkosto
Copy link
Author

rajkosto commented Feb 8, 2025

I've updated this code to also search/replace the override disables in the ApplicationOntology fingerprint.db which is the source of the starting values that the json file gets populated with when a new game gets detected, and then it sets the fingerprint.db to READ ONLY (setting the actual ApplicationStorage.json to READ ONLY causes NVContainer to crash occasionally so it's not a viable option)

So make sure to REDOWNLOAD AND RE-RUN THE EXE if you already have it.

@AsCo1d
Copy link

AsCo1d commented Feb 10, 2025

Thanks a lot for the tool! It does the job perfectly.
Interesting, for how much it is viable in the long term, after app / driver updates, adding new games, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment