Welcome to Godot, the Unicode Layer for Windows 9x! The GODOT subdirectory builds the actual DLL. The DELAY subdirectory builds the LIB file that should be shipped with the DLL. This LIB file acts as the custom loader that gives the same functionality as DELAYLOAD without forcing us to keep others from delay loading. Do NOT use the LIB file from the GODOT subdirectory! ---------------------------------------------- Random Notes: We have *no* CRT dependency, thus the SOURCES files in both subdirs has "USE_NOLIBS=1". If you unintentionally add a dependency, this will explain why you broke the build. Also, we set "NOT_LEAN_AND_MEAN=1" for the DLL since we need all the extra types for our types db. Here is a quick glance at how the build works: (1) GenThnk is used in the GODOT subdirectory to build both our thunking file that contains all of the APIs (GODOT\Win9xU.c) and our failure templates (failure.c and failure.h) (2) The loader template (DELAY\thunk_stub.c) is used to generate a seperate file for *each* API we wrap. We then compile each of those files (making use of the failure.c/failure.h that was generated in #1, above. It is done this way to avoid duplicate definition warnings. (3) The DLL itself is then compiled and linked, in GODOT\$(O) (4) The loader LIB is compiled, in DELAY\$(O) (5) Note that several APIs (24 altogether) are wrapped but have no implementation; they basically just call the "W" stub. This is to facilliate the customer's ability to override the API. A brave soul could decide to implement these functions at a later date if they wanted to. (6) TEST changes have been checked into both the COMMONTEST and PUBLICTEST depots, under the GODOTUNICODELAYER environment flag. ---------------------------------------------- TO ADD A DLL: (1) Add the DLL name to to godot\api.lst, preprended by a semicolon. ex: ;kernel32.dll ---------------------------------------------- TO ADD AN API: (1) For "W" APIs, add the undecorated API name to godot\api.lst. This list is alphabetical under the DLL name. For "A" APIs, including "A", and for undecorated ones just put them in straight. ex: EnableWindow GetWindowLongA GetWindowLong (2) If the API is never decorated (no A/W version) or A decorated then modify bldfiles.pl to properly autogenerate. Search for where $stUndecorated is used in the Perl script, and try not to make fun of my very meager Perl talents. Note that you *will* need special handling for any function in this category (see #4 below). (3) Add the API to delay\apithnk.lst. This list MUST be alphabetical in order of dll and case-sensitive full name of the function. Ex: .dll,kernel32,SetVolumeLabelW, _SetVolumeLabelW@8 .dll,kernel32,WriteProfileStringW, _WriteProfileStringW@12 .dll,kernel32,lstrcatW, _lstrcatW@8 .dll,mpr,MultinetGetConnectionPerformanceW, _MultinetGetConnectionPerformanceW@8 Note that uppercase W comes before lowercase l, above. You can get the actual full API name the same way we did, from a "link –dump –exports " call. (4) If any special handling is required, then create an [EFunc] template for the API in GODOT\unicows.tpl, which will be used instead of the autogenerated one. See any of the 250+ [EFunc] entries in Unicows.tpl for details. (5) If any special failure handling is required (rare), then you will create an [EFunc] template in GODOT\failure.tpl. The failure function is what will be called any time the API load fails (unlikely but possible in low memory situations). The failure call should mimic the way the OS stubs out unimplemented APIs. For an example, see any of the few failure templates in that file. Note that when the customer compiles against unicows.lib (which contains over 400 of these stubs, the linker will optimize this into less than 12-15 function calls since there are only so many diffrent failure functions. Optimizing for either size or speed will cause this to happen. The reason that unicows.lib is so large is that we are doing ahead of time what the linker would usually do at link time. ---------------------------------------------- CONSIDERs for future implementers/owners: (1) Currently we are not wrapping the "A" messaging functions. The side effect of this is that there are times when we will do A->W->A conversions when we could have skipped the conversions altogether and kept is as ANSI. We could wrap those functions, instead, and avoid the hassle. See GodotDoCallback for an example of a case where we *do* this - for ANSI windows receiving a message. Another example can be seen in GodotTransmitMessage/TransmitHelper for Unicode windows. (2) We currently use a similar strategy for our own Unicode windows. We will always convert W->A->W for messages, so we can give the system ANSI and the client Unicode. But there are some cases we could optimize this. See GodotDoCallback for another example where the code is in place do to this properly Ithe fUnicodeSrc param). (3) There is no support for conversion of parameters for SetWindowsHook/SetWindowsHookEx calls. This would be a major undertaking, but it is at least as possible as anything else we have done here. (4) We are not doing any UNLOAD work right now. We basically have: (A) each API pointer in a section named .data$. The linker would merge them all into .data and would sort based on the dll/api. We could support unloading them, but this would require us to keep track of what we've done so we can put the data back (just memcpy them in all at once). (B) For the NT case, we have up to 10 API handles obtained by LoadLibrary calls that we will not have freed at process close time. These handles will be in the user's code, not ours. We cannot free them in DLL_PROCESS_DETATCH since PSDK docs insist this would be bad juju. (C) For the Win9x case, we have one handle in the user's code (for unicows.dll) and up to six handles for other DLLs in our code. We cannot free them in DLL_PROCESS_DETATCH, as discussed in (B), above. All of these items will be freed at process detatch time. But it would be nice to do something better here. (5) We could support smart card APIs (Win95 OSR 2.1 and later). This would mean the following APIs: GetOpenCardName SCardAddReaderToGroup SCardConnect SCardForgetCardType SCardForgetReader SCardForgetReaderGroup SCardGetProviderId SCardIntroduceCardType SCardIntroduceReader SCardIntroduceReaderGroup SCardListCards SCardListInterfaces SCardListReaderGroups SCardListReaders SCardLocateCards SCardRemoveReaderFromGroup SCardSetCardTypeProviderName SCardStatus Note that these APIs will not exist on any Win9x platform unless the DLL is specifically installed (it comes from the PSDK). It might be better to have them recompile with us rather than trying to wrap them, anyway. ---------------------------------------------- Special thanks to (in alphabetical order): Gerardo Bermudez (GerardoB) - who has clearly forgotten more about user messaging that most people will ever know! Barry Bond (BarryBo) - who did the inital proof of concept that we took and ran 400 miles with! Raymond Chen (RaymondC) - who helped with many random Win9x issues that I ran across during this project. Chris Jones (ChrisJo) - who said yes to doing this project so I could get paid! Jay Krell (JayKrell) - who helped navigate through the myriad of issues with DllMain and TLS allocation issues. Phil Lucido (PhilipLu) - who helped us shed our CRT dependency. Mike Sheldon (MikeSh) - who helped point to a solid model for our subclass tracking. Dan Spalding (DanS) - who helped us with our initial delayload work that served us well till we found something better! Bryan Tuttle (BryanT) - who did most of the work for the loader! Who else could simply write their own delayload??? Michael S. Kaplan (v-michka) Trigeminal Software, Inc. http://www.trigeminal.com/ 16 March 2001