VOGONS


First post, by myne

User metadata
Rank Member
Rank
Member

I was playing around with an old 9x box and drivers are a pain.
The library here is great, but I wish there was an online driver library to AUTOMATICALLY find drivers.
Or at least some sort of pack that can be looked up from a fresh machine.

I didn't do that.
I did what I think might be the first bit required:
Getting the drivers from a working install into a workable structure including versioning (I used the driver date in YYYYMMDD) that maybe, just maybe, someone will figure out a way to make a more automated driver library.

The script does not intentionally modify any existing files or the registry.
There is no reason it should. Weird bugs happen though.

The coding style... uh... it works. COMMAND.COM is more limited than CMD 🙁
Frankly, it's pretty horrible what had to be done. command.com doesn't have: IF with ELSE, (proper code blocks), FOR in a very useful format, WHILE, and a bunch of other things.
Ever made a while loop with if and goto?
How about if/else with gotos?
It's not pretty. I'm honestly a bit surprised that I got it to work at all.

Dependencies:
reg.exe in the win98 resource kit: https://archive.org/details/mswin98rskt
gawk.exe available here: https://gnuwin32.sourceforge.net/packages/gawk.htm
MSVCP60.dll available here: https://www.dll-files.com/msvcp60.dll.html (I used V 6.0.8168.0 but others might work)
xset.exe available here: https://xset.tripod.com/

How it works:
Reads the registry and finds PCI devices in HKLM\enum\pci
Follows that trail to find details and the INF file that installed them
Attempts to find the INF in (windows directory)\inf and inf\other
Reads the INF looking for the names of the files required
Scans the windows directory for the listed files
Copies the inf and required files to (this folder)\Drivers with subdirectories for driver class, and the driver folder includes its date version
Updates a 'master list' (VenDevList.txt of ALL vendor and device ids listed in each INF with the path to the driver (I figure this would be the index file if anyone ever put it into an online database)

How to use:
Download attached script with dependencies OR
Copy the code below into notepad.
Save as a .bat (I used drvbak.bat)
Get the 3 dependencies into the same folder
Run it from... Well, I've only tested it on the C drive of a 98 box, so I'm going to say put it in a folder in the C drive somewhere. It might run from d: etc, but I don't know.

If you get out of environment errors, configure the dos window with more memory
I used initial environment 4096, EMS 8192, XMS 8192, DPMI 2048
In theory it will run from dos mode.

I'm curious:
1) if anyone cares
2) if anyone likes it
3) how awful you all think my code is. Some could be revised already, I know, but if it ain't broke...
4) how badly it's going to completely fuck up on someone else's machine

rem Crazy batch script to attempt to backup win9x drivers
rem Version 2/11/23
rem DD/MM/YY for you crazy yanks

@echo off

rem check for dependencies
set depend=yes
echo.
if not exist reg.exe echo You must have reg.exe in the same folder as this script
if not exist reg.exe echo It is in the win98 resource kit: https://archive.org/details/mswin98rskt
if not exist reg.exe set depend=no
if not exist gawk.exe echo You must have gawk.exe in the same folder as this script
if not exist gawk.exe echo It is available here: https://gnuwin32.sourceforge.net/packages/gawk.htm
if not exist gawk.exe set depend=no
if not exist MSVCP60.dll echo You must have MSVCP60.dll in same folder as this script to run gawk
if not exist MSVCP60.dll echo V 6.0.8168.0 available here: https://www.dll-files.com/msvcp60.dll.html
if not exist MSVCP60.dll set depend=no
if not exist xset.exe echo You must have xset.exe in same folder as this script to run gawk
if not exist xset.exe echo Available here: https://xset.tripod.com/
if not exist xset.exe set depend=no

echo.
rem exit if reg and gawk aren't available
if %depend%==no goto eof

xset a=
cls
rem running the script with /s will skip the intro/disclaimer
if [%1]==[/s] goto clearvars

echo.
echo.
Echo This script is intended to backup EXISTING PCI drivers on Windows 9x/ME
Echo It is unlikely to work on other versions due to registry differences.
echo.
Echo === How it works ===
Echo 1) Reads the registry and finds PCI devices in HKLM\enum\pci
Echo 2) Follows that trail to find details and the INF file that installed them
Echo 3) Attempts to find the INF in (windows directory)\inf and inf\other
Echo 4) Reads the INF looking for the names of the files required
echo 5) Scans the windows directory for the listed files
echo 6) Copies the inf and required files to (this folder)\Drivers
echo.
echo Note: Running with /s skips this message
echo.
echo The script does not intentionally modify any existing files or the registry.
echo There is no reason it should. Weird bugs happen though.
echo The coding style... uh... it works. COMMAND.COM is more limited than CMD :(
echo Continue at your own risk...
echo.
echo.
Xset /prompt "Press X to exit, or anything else to continue: " contyn

if %contyn%==x goto eof
if %contyn%==X goto eof


rem clear all the variables
:clearvars
Show last 283 lines
set contyn=
set write=
set countd=
set vtemp=
set vtemp2=
set vtemp3=
set vtemp4=
set lineno=
set exists=
set isinf=
set drvdatetemp=
set startline=
set pcitemp2=
set depend=
set classtemp=
set classlist=
set pcilist=
set inftemp=
set inflist=
set pcilist=
set drvlist=
set inflist=
set drvdatelist=
set ddesclist=
set pcitemp=
set drvtemp=
set inftemp=
set classtemp=
set pcivar=
set drvversion=
set drvname=
set infname=
set pname=
set curdir=
set ddesctemp=
set authortemp=
set fpath=
set xset_msg=
if exist filelist.txt del filelist.txt
if exist err.txt del err.txt
if exist flist2.txt del flist2.txt

if %end%==end goto end

rem set some stuff
xset startline=4
xset lineno=%startline%
xset countD=1


echo VEN-DEV;Class;driver author;device name;driverdate;infname > driverlist.csv
cls
Echo Looking in the registry for PCI devices
echo.
echo Manufacturer Device Description Driver Date
echo ------------ ------------------ -----------
:loop1start
rem *****************************************************************
rem loop through the pci subkeys in the registry until "end of file"
rem this is basically a while loop done with goto because... dos :/

rem Looking in the registry for PCI devices
reg query HKLM\enum\pci | xset /line %lineno% pcitemp
rem if EOF exit loop
if [%xset_msg%]==[END-OF-FILE] goto loop1end
rem trim brackets
xset /left -1 pcitemp=%pcitemp%
xset /right -1 pcitemp=%pcitemp%
rem trim back to vendor/device, replace ampersand into variable pci(#)
xset /left 17 pcitemp2=%PCItemp%
rem xset /left 17 vtemp=%pcitemp%
rem xset /left 8 vtemp2=%vtemp%
rem xset /right 8 vtemp3=%vtemp%
rem xset pcivar=%vtemp2%-%vtemp3%
xset pcivar=%pcitemp2%;
rem add to variable pcilist
xset /append pcilist=%pcitemp2%;

rem find the class in registry
reg query hklm\enum\pci\%pcitemp% /s | find /i "Class " | xset /mid 17 50 classtemp
xset /append pcivar=%classtemp%;
xset /append classlist=%classtemp%;

rem find the driver location in registry
reg query hklm\enum\pci\%pcitemp% /s | find /i "Driver" | xset /right -17 drvtemp

rem find the driver author in registry
reg query hklm\system\currentcontrolset\services\class\%drvtemp% /s | find /i "providername" | xset /mid 24 50 authortemp
xset /append pcivar=%authortemp%;

rem Finding name of driver based on above location
reg query hklm\system\currentcontrolset\services\class\%drvtemp% /s | find /i "driverdesc" | xset /mid 22 50 ddesctemp
rem add inf to variable ddesclist
xset /append ddesclist=%ddesctemp%;
rem add inf to variable pci(#)
xset /append pcivar=%ddesctemp%;

rem find driver date
reg query hklm\system\currentcontrolset\services\class\%drvtemp% /s | find /i "driverdate" | xset /mid 22 10 drvdatetemp

rem rearrange date from MMDDYYYY to YYYYMMDD and add to var drvdatetemp (assuming it's consistently US formatted MM-DD-YYYY)
rem fix leading blank if single digit month
xset /left 10 drvdatetemp=%drvdatetemp%
rem check if it is a single digit month
xset /mid 2 1 vtemp2=%drvdatetemp%
rem fix single digit month
if [%vtemp2%]==[-] xset drvdatetemp=0%drvdatetemp%
rem finally set the damn month
xset /left 2 vtemp2=%drvdatetemp%
rem get day
rem but first fix the single digits
xset /mid 4 2 vtemp3=%drvdatetemp%
xset vtemp3=%vtemp3%
xset /length vtemp4=%vtemp3%
if [%vtemp4%]==[1] xset vtemp3=0%vtemp3%
rem get Year
xset /right 4 vtemp=%drvdatetemp%

rem rearrange into YYYYMMDD
xset drvdatetemp=%vtemp%%vtemp2%%vtemp3%
xset /append drvdatelist=%drvdatetemp%;
rem add to var pci(#)
xset /append pcivar=%drvdatetemp%;

rem find name of inf
reg query hklm\system\currentcontrolset\services\class\%drvtemp% /s | find /i "infpath" | xset /mid 19 50 inftemp
rem add inf to variable inflist and 2
xset /append inflist=%inftemp%;
rem add inf to variable pci(#)
xset /append pcivar=%inftemp%

rem see if the inf is in the inf dir
set exists=0
if exist %windir%\inf\%inftemp% set exists=1
if exist %windir%\inf\%inftemp% echo %windir%\inf\%inftemp% >> filelist.txt
if not [%Exists%]==[1] if exist %windir%\inf\other\%inftemp% set exists=2
if exist %windir%\inf\other\%inftemp% echo %windir%\inf\other\%inftemp% >> filelist.txt
if [%exists%]==[0] echo $%inftemp% NotFound >> filelist.txt

rem if not exist %windir%\inf\%inftemp% echo $%inftemp% NotFound >> filelist.txt
rem if exist %windir%\inf\%inftemp%

rem the syntax of this can best be described as "are you on drugs?" but here goes...
rem if exists (set above) is 1 then it's in the inf dir, gawk (search) the file, ignoring case for "[*copyfiles]" and 'flag' the lines between that and the next "[" for output to filelist.txt
if [%exists%]==[1] gawk.exe "BEGIN{IGNORECASE = 1} /\[.*copyfiles/ {flag=1;next} /\[/ {flag=0} flag" %windir%\inf\%inftemp%>> filelist.txt
rem same as above but it's in the "other" subfolder
if [%exists%]==[2] gawk.exe "BEGIN{IGNORECASE = 1} /\[.*copyfiles/ {flag=1;next} /\[/ {flag=0} flag" %windir%\inf\other\%inftemp%>> filelist.txt

echo %errorlevel% %inftemp% >> err.txt



echo %PCIvar% >> driverlist.csv
xset /left 22 vtemp=%authortemp%
xset /left 45 vtemp2=%ddesctemp%
echo %vtemp% %vtemp2% %drvdatetemp%


rem increment counters
xset /math lineno = %lineno% + 1
xset /math CountD = %CountD% + 1
goto loop1start
:loop1end
rem don't forget old dos has 8char labels! damnit.


rem gotta drop the count by 1 because the eof check comes after the increment
xset /math CountD = %CountD% - 1

echo.
Echo Found %CountD% PCI drivers
echo.
rem *****************************************************************


rem echo loop

xset lineno=1
if exist flist2.txt del flist2.txt
echo Searching for the driver files

rem this loop is to get all the files referenced in the inf files
:loop2start
rem again, basically a "while not end of file"
type filelist.txt | xset /line %lineno% vtemp
rem if EOF exit loop
if [%xset_msg%]==[END-OF-FILE] goto loop2end
rem check first char isn't error ($)
rem hack to work around dos' weird handling of semicolons while setting vtemp2 to the 1st char of vtemp. note the "%vtemp%#" in case it's blank in which case it will be #
echo %vtemp%# | gawk "{gsub(\";\",\"#\"); print}" | xset /left 1 vtemp2
rem if it is $, echo to err.txt
if [%vtemp2%]==[$] echo %vtemp% >> err.txt
rem try and trim the bullshit from the drivername - it looks like it's usually commas. Might need editing if more are found
xset /separator "," /word 1 vtemp3=%vtemp%

rem figure out if it was a comment in the original inf (; replaced by #) or an error set above ($) and write it to a file if not
xset write=yes
if [%vtemp2%]==[$] xset write=no
if [%vtemp2%]==[#] xset write=no
rem if [%vtemp2%]==[ ] xset write=no
rem if [%vtemp2%]==[] xset write=no
rem pause
if %write%==yes echo %vtemp3% >> flist2.txt
rem increment counters
xset /math lineno = %lineno% + 1

goto loop2start
:loop2end


rem now to find and copy the drivers into folders
xset lineno=1
echo Finding and copying driver files. This could take a minute or so...
cd | xset curdir
:loop3start
rem echo on

set isinf=n
rem again, basically a "while not end of file"
type flist2.txt | xset /line %lineno% vtemp
rem if EOF exit loop
if [%xset_msg%]==[END-OF-FILE] goto loop3end
rem check if inf
xset /separator "." /UPPER /word 2 vtemp2=%vtemp%
rem this should be if var=inf, but the only way to do code blocks is like this
if not %vtemp2%==INF goto skipinf
rem ok so this is a bit retarded but to get the second last word (filename without extension) we have to reverse it, get the 2nd word and rereverse it
xset /reverse vtemp3=%vtemp%
xset /separator "\." /word 2 vtemp3=%vtemp3%
xset /reverse vtemp3=%vtemp3%
rem same to get the full inf filename back
xset /reverse infname=%vtemp%
xset /separator "\" /word 1 infname=%infname%
xset /reverse infname=%infname%
rem now we have the name of the driver, gotta look up the date from drvdatelist by first matching the # from inflist
xset countd=1
rem basically this is an if/else done the worst way possible. First part "if" inf, "else" is file with weird overlapping gotos ugh.
:loop31start
echo %inflist% | xset /separator ";" /word %countd% drvname
if [%xset_msg%]==[END-OF-FILE] goto end31loop
if %drvname%==%infname% echo %drvdatelist% |xset /separator ";" /word %countd% drvversion
echo %classlist% | xset /separator ";" /word %countd% classtemp
if %drvname%==%infname% goto end31loop
xset /math CountD = %CountD% + 1
goto :loop31start
rem so its going to loop until the version is found or it runs out of 'words' in the variable... hopefully...
:end31loop
rem make dirs
if not exist %curdir%\drivers\nul md %curdir%\drivers
if not exist %curdir%\drivers\%classtemp%\nul md %curdir%\drivers\%classtemp%
if not exist %curdir%\drivers\%classtemp%\%vtemp3%-%drvversion%\nul md %curdir%\drivers\%classtemp%\%vtemp3%-%drvversion%
copy %vtemp% %curdir%\drivers\%classtemp%\%vtemp3%-%drvversion%
rem update driverlist
rem add all the vendor and device IDs to vendevlist.txt so in theory sometime later we might be able to implement a driver find utility
gawk.exe -F. "BEGIN{IGNORECASE = 1; } /^%%PCI\\/ { print $1\",.\\drivers\\%classtemp%\\%vtemp3%-%drvversion%\\%infname%.inf\" }" %vtemp% >> VenDevList.txt
goto skipdrv
rem Told you there were weird overlapping gotos
:skipinf
rem find the driver files
cd %windir%
dir /s /b %vtemp% | %curdir%\xset fpath
cd %curdir%
copy %fpath% %curdir%\drivers\%classtemp%\%vtemp3%-%drvversion%
:skipdrv

xset /math lineno = %lineno% + 1

goto loop3start
:loop3end


rem clear all the variables and temp files
set end=end
goto clearvars

:end
set end=
dir /s /b .\drivers |more

echo.
echo In theory that should show your drivers which you can now backup for later.
echo.
:eof

Attachments

  • Filename
    DrvBak.zip
    File size
    373.4 KiB
    Downloads
    27 downloads
    File comment
    Script and dependencies
    File license
    Fair use/fair dealing exception
Last edited by myne on 2023-11-02, 10:20. Edited 2 times in total.

Reply 4 of 4, by Pierre32

User metadata
Rank Oldbie
Rank
Oldbie

I've had times I would have used this for sure. You land some old system, it's got a working 9x install. You want to start fresh, but that means you have to investigate all the bits and find the drivers online. Thanks for sharing - I'll give it a whirl next time I've got a suitable box on the desk.