/* An example script that FUNCDEFs some Windows OS functions to retrieve * information about a file that is a DLL, EXE, driver, font, etc. */ /* So that we don't need to use the CALL keyword */ OPTIONS "C_CALL" /* Allow 32-bit addresses to be stored without exponential notation. * Some OS functions may cause Reginald to deal with storing 32-bit * addresses, and we don't want those stored in exponential form. */ NUMERIC DIGITS 10 /* ============ FUNCDEF the OS functions we need ============ */ /* Make things easy for us with WINFUNC option */ OPTIONS "WINFUNC NOSOURCE" /* Let's CATCH FAILURE for the following FUNCDEF statements, so we * don't have to test if each one succeeded */ DO FUNCDEF("GetModuleHandle", "void *, str", "kernel32", , "O") FUNCDEF("FreeLibrary", "void, void", "kernel32") FUNCDEF("LoadLibrary", "void *, str", "kernel32", , "O") FUNCDEF("GetFileVersionInfoSize", "32u, str, 32u * stor", "version") FUNCDEF("GetModuleFileName", "32u, void, str[260] stor, 32u", "kernel32") FUNCDEF("GlobalAlloc", "void *, 32u, 32u", "kernel32", , "O") FUNCDEF("GlobalFree", "void, void", "kernel32") FUNCDEF("GetFileVersionInfo", "32u, str, 32u, 32u, void", "version") FUNCDEF("GetLastError", "32u", "kernel32") FIXEDFILEINFO = "32u, 32u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 32u, 32u, 32u, 32u, 32u, 16u, 16u, 16u, 16u" FIXEDFILEPTR = "struct FIXEDFILEINFO *" FUNCDEF("GetFixedFileVersInfo", "32u, void, str, struct FIXEDFILEPTR stor, 32u * stor", "version", "VerQueryValue") TRANSLATEINFO = "char[4]" TRANSINFOPTR = "struct TRANSLATEINFO *" FUNCDEF("VerQueryValue", "32u, void, str, struct TRANSINFOPTR stor, 32u * stor", "version") INFOSTR = "str *" FUNCDEF("VerQueryStr", "32u, void, str, struct INFOSTR stor, 32u * stor", "version", "VerQueryValue") CATCH FAILURE CONDITION('M') RETURN END /* Here's the name of the EXE/DLL/driver/font/etc file that we * want information upon. Here, we just use notepad. */ MyExeName = SEARCHPATH("%WIN%") || "notepad.exe" /* Assume that the dll/exe is already loaded into our process, and * just get its handle */ LibLoaded = 0 Module = GetModuleHandle(MyExeName) /* Not already loaded? */ IF Module == "" THEN DO /* Try to load it */ Module = LoadLibrary(MyExeName) /* If an error, then we just can't get info */ IF Module == "" THEN DO InfoErr1: err = GetLastError() /* NOTE: Hopefully, we call this before the interpreter happens to call some other OS function internally. */ SAY "Can't retrieve info about" MyExeName || "." || '0D0A'X || "Error #" || err SAY UNIXERROR(err) RETURN END /* Indicate that we must unload the module */ LibLoaded = 1 END /* Retrieve the full path and filename for the executable file containing * the specified module. */ length = GetModuleFileName(Module, fileName, 260 /* MAX_PATH */) /* Error? */ IF length == 0 THEN DO InfoErr2: IF LibLoaded == 1 THEN FreeLibrary(Module) SIGNAL InfoErr1 END /* Determine whether the operating system can obtain version information * about the file. If version information is available, GetFileVersionInfoSize * returns the size in bytes of that information. NOTE: GetFileVersionInfo works * only with Win32 DLL/Exes. It does not work with 16-bit Windows ones. */ length = GetFileVersionInfoSize(fileName, junk) IF length == 0 THEN SIGNAL InfoErr2 /* Allocate memory to hold the version information we'll retrieve */ VersionInfo = CONVERTDATA(0,"", "char[" || length || "]", "A") IF VersionInfo == "" THEN SIGNAL InfoErr2 /* Now retrieve the version information */ IF GetFileVersionInfo(fileName, , length, VersionInfo) == 0 THEN SIGNAL InfoErr2 IF GetFixedFileVersInfo(VersionInfo, "\", FIXEDFILEINFO, length) == 0 THEN SIGNAL InfoErr2 /* Print out the File and Product versions */ SAY "File version =" FIXEDFILEINFO.1.4 || "." FIXEDFILEINFO.1.3 || "." FIXEDFILEINFO.1.6 || "." FIXEDFILEINFO.1.5 SAY "Product version =" FIXEDFILEINFO.1.8 || "." FIXEDFILEINFO.1.7 || "." FIXEDFILEINFO.1.10 || "." FIXEDFILEINFO.1.9 /* Print out what type of file this is */ SELECT WHEN FIXEDFILEINFO.1.14 == 1 THEN SAY "Application" WHEN FIXEDFILEINFO.1.14 == 2 THEN SAY "Dynamic Link Library" WHEN FIXEDFILEINFO.1.14 == 3 THEN DO SELECT WHEN FIXEDFILEINFO.1.15 == 1 THEN SAY "Printer driver" WHEN FIXEDFILEINFO.1.15 == 2 THEN SAY "Keyboard driver" WHEN FIXEDFILEINFO.1.15 == 3 THEN SAY "Language driver" WHEN FIXEDFILEINFO.1.15 == 4 THEN SAY "Display driver" WHEN FIXEDFILEINFO.1.15 == 5 THEN SAY "Mouse driver" WHEN FIXEDFILEINFO.1.15 == 6 THEN SAY "Network driver" WHEN FIXEDFILEINFO.1.15 == 7 THEN SAY "System driver" WHEN FIXEDFILEINFO.1.15 == 8 THEN SAY "Installable driver" WHEN FIXEDFILEINFO.1.15 == 9 THEN SAY "Sound driver" WHEN FIXEDFILEINFO.1.15 == 10 THEN SAY "Comm driver" WHEN FIXEDFILEINFO.1.15 == 11 THEN SAY "Input driver" OTHERWISE SAY "Unknown type of driver" END END WHEN FIXEDFILEINFO.1.14 == 4 THEN DO SELECT WHEN FIXEDFILEINFO.1.15 == 1 THEN SAY "Raster Font" WHEN FIXEDFILEINFO.1.15 == 2 THEN SAY "Vector Font" WHEN FIXEDFILEINFO.1.15 == 3 THEN SAY "Truetype Font" OTHERWISE SAY "Unknown type of font" END END WHEN FIXEDFILEINFO.1.14 == 5 THEN SAY "16-bit driver" WHEN FIXEDFILEINFO.1.14 == 6 THEN NOP WHEN FIXEDFILEINFO.1.14 == 7 THEN SAY "Compiler lib" OTHERWISE SAY "Unknown type of file" END /* Print out what Windows operating system this file is for */ SELECT WHEN FIXEDFILEINFO.1.13 == 1 THEN SAY "For 16-bit Windows" WHEN FIXEDFILEINFO.1.13 == 2 THEN SAY "For 16-bit OS/2 Presentation Manager" WHEN FIXEDFILEINFO.1.13 == 3 THEN SAY "For 32-bit OS/2 Presentation Manager" WHEN FIXEDFILEINFO.1.13 == 4 THEN SAY "For 32-bit Windows" WHEN FIXEDFILEINFO.1.13 == 65536 THEN SAY "For MS-DOS" WHEN FIXEDFILEINFO.1.13 == 131072 THEN SAY "For 16-bit OS/2 (command line)" WHEN FIXEDFILEINFO.1.13 == 196608 THEN SAY "For 32-bit OS/2 (command line)" WHEN FIXEDFILEINFO.1.13 == 262144 THEN SAY "For 32-bit Windows (command line)" WHEN FIXEDFILEINFO.1.13 == 65537 THEN SAY "For MS-DOS or 16-bit Windows" WHEN FIXEDFILEINFO.1.13 == 65540 THEN SAY "For MS-DOS or 32-bit Windows" WHEN FIXEDFILEINFO.1.13 == 131074 THEN SAY "For 16-bit OS/2" WHEN FIXEDFILEINFO.1.13 == 196611 THEN SAY "For 32-bit OS/2" WHEN FIXEDFILEINFO.1.13 == 262148 THEN SAY "For Windows NT/2000/XP" OTHERWISE SAY "For unknown operating system" END /* The Win32 API contains the following predefined version information strings: * CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, * OriginalFilename ProductName ProductVersion. So let's query these. */ /* Get the translation information. Translation table consists of an array of * two WORD items. First item is language Id and second one is character set * which we'll use in subsequent queries. */ IF VerQueryValue(VersionInfo, "\VarFileInfo\Translation", TRANSLATEINFO, length) == 0 THEN SIGNAL InfoErr2 /* Format it so we can use it in subsequent queries */ TRANSLATEINFO = "\StringFileInfo\" || VALUEIN(TRANSLATEINFO.1.1, 1, 2, 'HV') || VALUEIN(TRANSLATEINFO.1.1, 3, 2, 'HV') || "\" /* Get company name */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "CompanyName", name, length) == 0 THEN SIGNAL InfoErr2 SAY "company name =" name.1 /* Get product name */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "ProductName", name, length) == 0 THEN SIGNAL InfoErr2 SAY "product name =" name.1 /* Get product version */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "ProductVersion", name, length) == 0 THEN SIGNAL InfoErr2 SAY "product version =" name.1 /* Get copyright information */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "LegalCopyRight", name, length) == 0 THEN SIGNAL InfoErr2 SAY "copyright information =" name.1 /* Get original file name */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "OriginalFileName", name, length) == 0 THEN SIGNAL InfoErr2 SAY "original file name =" name.1 /* Get file description */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "FileDescription", name, length) == 0 THEN SIGNAL InfoErr2 SAY "file description =" name.1 /* Get file version */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "FileVersion", name, length) == 0 THEN SIGNAL InfoErr2 SAY "file version =" name.1 /* Get internal name */ IF VerQueryStr(VersionInfo, TRANSLATEINFO || "InternalName", name, length) == 0 THEN SIGNAL InfoErr2 SAY "internal name =" name.1 /* Free memory for version info. NOTE: Rexx would do this automatically when this script ends, * but here's how you explicitly free memory */ CALL CONVERTDATA(VersionInfo,"",,"=") /* Free any loaded module */ IF LibLoaded == 1 THEN FreeLibrary(Module)