Hey,
As you've probably noticed, I've been working on implementing advpack for a couple months now; a lot of progress has been made, and I'm glad to say that the end is in sight. The rest of this email details the game plan for finishing advpack.
advpack has five main install functions: DoInfInstall, ExecuteCab, LaunchINFSection, LaunchINFSectionEx, and RunSetupCommand. They all basically do the same thing with minor differences in functionality. ExecuteCab extracts the files to install from a cab archive, LaunchINFSectionEx provides backup and rollback capability, and RunSetupCommand can also launch executables. When installing an INF section, advpack calls setupapi to install the base INF commands, such as CopyFiles and AddReg. After this, advpack parses the Advanced INF for advanced commands that are only installable when using advpack. These commands include:
Values: RequiredEngine - Use either setupapi or setupx, we will ignore it. CustomDestination - assigns ldids to extra directories. SmartReboot - same reboot options as LaunchINFSection. Cleanup - deletes the INF when the install/uninstall is finished if this is 1. CheckAdminRights - check if the user is admin if this is 1.
Actions: RegisterOCXs UnregisterOCXs BeginPrompt EndPrompt RunPreSetupCommands RunPostSetupCommands DelDirs PerUserInstall
Backup/Rollback: ComponentName ComponentVersion BackupReg PreRollBack BackupPath
Internally, there will be three main install functions: install_init, which will open the INF, make sure it's legit, and other initializations, spapi_install, which will call setupapi to install the base INF commands, and adv_install, which will parse the install section and run the provided commands. Each advanced command will be implemented by a function of similar name, e.g., RegisterOCXs would be implemented by the function register_ocxs, etc. All the command functions will be in a hash map, the key being the command name, the value being a pointer to the function that implements the command. adv_install will use setupapi to parse the entries of the install section, calling the function returned by a query to the hash map. According to INF Web [1], some commands are run before others, so there will probably be three or four maps, the functions in the maps grouped according to the order in which the commands should be run. For example, RunPreSetupCommands is to be executed after the BeginPrompt command, so begin_prompt would be in the phase 1 map, and run_pre_setup_commands would be in the phase 2 map. We would call the parser like so:
run_adv_commands("InstallSection", phase1_map); run_adv_commands("InstallSection", phase2_map); run_adv_commands("InstallSection", phase3_map);
If a command in the install section is not in the map, we just ignore it.
This is The Plan so far, so if anyone has any ideas or suggestions, I'd love to hear from you.
Thanks, James Hawkins
On Thu, 2006-03-30 at 23:12 -0600, James Hawkins wrote:
there will probably be three or four maps, the functions in the maps grouped according to the order in which the commands should be run.
Or maybe simpler, instead of storing just the function pointer as the value for the map, store a structure that has 2 fields: -- priority -- function
So than you just call things as: for (i=0; i < MAX_PRIO; i++) run_adv_commands("InstallSection", i, phase_map);
And ignore entries with incorrect priorities.
On 3/31/06, Dimi Paun dimi@lattica.com wrote:
Or maybe simpler, instead of storing just the function pointer as the value for the map, store a structure that has 2 fields: -- priority -- function
So than you just call things as: for (i=0; i < MAX_PRIO; i++) run_adv_commands("InstallSection", i, phase_map);
And ignore entries with incorrect priorities.
Thanks Dimi, that's a really good idea! I'll incorporate that into the design.
-- James Hawkins
"James Hawkins" truiken@gmail.com writes:
Internally, there will be three main install functions: install_init, which will open the INF, make sure it's legit, and other initializations, spapi_install, which will call setupapi to install the base INF commands, and adv_install, which will parse the install section and run the provided commands. Each advanced command will be implemented by a function of similar name, e.g., RegisterOCXs would be implemented by the function register_ocxs, etc. All the command functions will be in a hash map, the key being the command name, the value being a pointer to the function that implements the command. adv_install will use setupapi to parse the entries of the install section, calling the function returned by a query to the hash map. According to INF Web [1], some commands are run before others, so there will probably be three or four maps, the functions in the maps grouped according to the order in which the commands should be run. For example, RunPreSetupCommands is to be executed after the BeginPrompt command, so begin_prompt would be in the phase 1 map, and run_pre_setup_commands would be in the phase 2 map. We would call the parser like so:
run_adv_commands("InstallSection", phase1_map); run_adv_commands("InstallSection", phase2_map); run_adv_commands("InstallSection", phase3_map);
If a command in the install section is not in the map, we just ignore it.
That hash map thing sounds like overkill to me. You have only a few sections you know you will handle, you can just look for these explicitly, like setupapi does. And if you look them up in the order they should be executed you don't need the different phases either.
James Hawkins wrote:
Internally, there will be three main install functions: install_init, which will open the INF, make sure it's legit, and other initializations, spapi_install, which will call setupapi to install the base INF commands, and adv_install, which will parse the install section and run the provided commands.
I'm quite sure RunPreSetupCommands gets executed before the base INF commands. I'm not sure wether there are others (BeginPrompt, BackupReg comes to mind). So you need two install functions like adv_install_pre and adv_install_post.
This is The Plan so far, so if anyone has any ideas or suggestions, I'd love to hear from you.
Why not simply use the same mechanism as in setupapi [1]? My patch [2] back in january was using it, and it looked like a good idea.
Markus
[1] http://source.winehq.org/source/dlls/setupapi/install.c [2] http://www.winehq.org/pipermail/wine-devel/2006-January/044083.html