| I would like to (re-implement) a Windows layer on top of an MSDOS layer - noting that I am willing to rewrite application code once I have rules in place. Suitable rules may already exist - maybe I just don't know them.
 First the Windows calls:
 
 HANDLE FindFirstFileA(file_pattern, data_returned);
 
 BOOL FindNextFileA(HANDLE h, data_returned);
 
 BOOL FindClose(HANDLE h);
 
 Now thanks to the flexibility of handles - this allows me to open two directories independently. There is no need for them to clash with each other. I can potentially open dir A, then open dir B, and then close dir A, and then close dir B. Instead of recursion.
 
 It so happens that my needs are less than that - it is enough for me to be able to do open A, open B, close B, close A. The greater flexibility would be great, but not necessary.
 
 MSDOS instead has the equivalent of:
 
 int PosFindFirst(char *pat, int attrib); /* func 4e */
 int PosFindNext(void); /* func 4f */
 void *PosGetDTA(void); /* func 2f */
 
 Now originally I thought that I needed to add a PosFindClose() extension, to provide the same flexibility that Windows has - to let the OS know that I've finished processing this directory.
 
 But at least for my usual needs - at least on the application level - specifically implementing zip - there is the knowledge of a close already - the close happens automatically when FindNext returns non-zero.
 
 So when that happens, it would be in a position to free up any resources (flexible rules for any theoretical MSDOS replacement - regardless of how MSDOS does it currently).
 
 But to work within the current limitations of MSDOS, you could perhaps create a PosFindClose extension, but if it is "unsupported function" then you are required to read to the end of the directory - even if you don't want to - so that a theoretical MSDOS clone with no extensions can free up any resources it is using as the result of the FindFirst that caused it to open in the first place.
 
 Next, what options does a theoretical MSDOS implementation have with the above calls?
 
 As far as I know, current MSDOS only has a single DTA, so if you do a second FindFirst for recursion purposes, the DTA gets clobbered and there is a disaster - unless the application itself takes responsibility for preserving this system structure - the DTA.
 
 That seems like a fundamentally bad design to me - but - with reasonable rules - we may be able to recover.
 
 I can see in my current code that I first get the DTA in preparation for calling FindFirst.
 
 But maybe that order needs to be reversed.
 
 First, here is how the API could work with that order.
 
 And note - I am opening up the possibility of multiple DTAs now, instead of "the" DTA.
 
 
 METHOD ONE (my NON-preferred way at the moment)
 
 You aren't supposed to just get "the" DTA whenever you feel like it. What you are supposed to do is do a GetDTA call in preparation for some new operation. This gives the OS an opportunity to allocate a NEW DTA and give you a pointer to it. The next operation you do will then operate on that new DTA. If that is a FindFirst/FindNext, then that DTA will be freed when the FindNext hits the end of directory.
 
 
 METHOD TWO (I think this is better)
 
 FindFirst is allowed to cause the creation of a new DTA. Applications must retrieve the current DTA after doing this operation, instead of assuming it is the same as it was before the operation. "MSDOS-clones" are guaranteed to keep the DTA the same until the last successful FindNext, so you are not required to requery the *current* DTA every time you call FindNext.
 
 You do retain the right to query the current DTA whenever you want, if that serves some purpose.
 
 
 Next - rules to work within the *current* MSDOS - warts and all. This is a single DTA, and no preservation (as far as I am aware).
 
 So, assuming method two is being used, you've done a findfirst, retrieved the DTA, you're doing findnext calls, everything is working fine, then you decide to recurse - or even open an unrelated directory. The application is required to do the following:
 
 1. Preserve a copy of the DTA up to the filename. Also preserve the address of the DTA.
 
 2. Open the other (sub-)directory with FindFirst.
 
 3. Get the current DTA.
 
 4. If the current DTA is different from the previous DTA, then this is a "sophisticated" MSDOS and you don't make any assumptions about it and you don't touch the DTAs.
 
 5. If some flavor of MSDOS still has the same DTA that was previously being used, then, when you've finished with the new directory, and you wish to go back to the previous directory you were traversing, you need to:
 
 A. (Potentially) Do a fresh GetDTA to see where you stand. This gives MSDOS some opportunity to close a current FindNext sequence, even if it hasn't completed, and switch back to the previous DTA in the stack of DTAs.
 
 B. If you're still at your original old pointer, then you need to first check to see if the contents of the the DTA match what you have already saved. ONLY if they are different, should you copy the saved contents back to the DTA area. Your application could potentially be running in PM16 and you no longer have the ability to write to system memory, so you can't unconditionally copy it.
 
 C. (Potentially) If you're not at your original old pointer, that is an indication that "MSDOS" (future, present, clone) knows what it is doing already, and you shouldn't interfere with the system memory - even if you do have write access.
 
 Note that it may simply be that I have been conceptually wrong for decades, and there are already multiple DTAs, and I have just been using the APIs incorrectly and causing myself problems.
 
 Note that right at the moment I don't see how to make it work with the current APIs, two independent directories being opened, and neither of them having reached the end. Maybe GetDTA could be defined to round-robin the current DTAs in the opposite order to which they were opened, and if you keep track of where you originally were, you can wait until it gets back to that?
 
 Any thoughts?
 
 Thanks. Paul.
 |