First post, by mkarcher
The official full-featured support for the EMU8K wave table synthesizer only applies for Windows 95, Windows 98 and Windows NT 4.0 . It is known that you can install the Windows NT 4.0 driver in Windows 2000 or Windows XP if you jump through some hoops, see http://sannata.org/articles/sb_awe64_xp_soundfonts.shtml (you might need machine translation of that page if you don't speak russian). That page basically tells you to remove the AWE32 WDM driver in Windows 2000/XP and install the NT 4.0 driver instead, ignoring any warnings that the driver isn't signed, PnP compliant or verifyable the right one for your PnP SB (AWE)32/64.
The driver installation worked out-of-the-box for me. But the AWE32 control panel didn't work, even after enabling the compatibility property page in the properties for LNK files and choosing "NT 4.0 SP5", as suggested on that page.
It turns out that both Creative Labs and Microsoft themselves blatantly violate the Win32 programming rules about what you may do from DllMain several times in their setup. The worst offender is WINMM.DLL, a Microsoft library. The Windows NT version of SBAWE32.DRV can both be loaded as driver and as DLL. It depends on WINMM.DLL, so loading SBAWE32.DRV will automatically also load WINMM.DLL. WINMM.DLL performs some registry access from it's DllMain function, in direct violation of Microsoft's specification what is safe in DllMain. That documentation page directly describes the issue: "You should never perform the following tasks from within DllMain: [...] Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash."
The problem with AWECP32.EXE ist that it directly links to AWEMAN32.DLL, and AWEMAN32's DllMain function uses LoadLibrary to load SBAWE32.DRV (another thing that's forbidden by MS rules). Windows 2000 maps all DLLs mentioned in an EXE file into memory, and the initializes them in the order they are mentioned. AWECP32.EXE links to both AWEMAN32.DLL and ADVAPI32.DLL, but mentions AWEMAN32.DLL before ADVAPI32.DLL, so AWEMAN32.DLL gets initialized before ADVAPI32.DLL, and initializing AWEMAN32.DLL loads SBAWE32.DRV. Loading SBAWE32.DRV causes the dependent library WINMM.DLL to be loaded and intialized. The initialization code of WINMM.DLL uses the registry functions while ADVAPI32.DLL is still not initialized. This causes a crash, which is caught by LoadLibrary (for SBAWE32.DLL), so in effect, loading SBAWE32.DRV fails with an error code.
The easiest way to deal with this issue is to modify the order of the entries in the import table of AWECP32.EXE. If AWEMAN32.DLL is moved from the first position in the import list to the last position, ADVAPI32.DLL is already initialized when AWEMAN32.DLL loads SBAWE32.DRV, so the rule violation is benign now. I used CFF Explorer to find the offset of the import structures, and shuffled the import descriptor using HxD, but there might be higher-level tools to achieve the same goal.