source: trunk/src/helpers/level.c@ 20

Last change on this file since 20 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 24.8 KB
Line 
1
2/*
3 *@@sourcefile level.c:
4 * contains helper functions for querying SYSLEVEL files.
5 *
6 * This is all new with V0.9.2.
7 *
8 * Function prefixes:
9 * -- lvl* syslevel helpers
10 *
11 *@@added V0.9.2 (2000-03-08) [umoeller]
12 *@@header "helpers\level.h"
13 */
14
15/*
16 * Copyright (C) 1994 Martin Lafaix (EDM/2 2-05).
17 * Copyright (C) 2000 Ulrich M”ller.
18 * This file is part of the "XWorkplace helpers" source package.
19 * This is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published
21 * by the Free Software Foundation, in version 2 as it comes in the
22 * "COPYING" file of the XWorkplace main distribution.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 */
28
29#define OS2EMX_PLAIN_CHAR
30 // this is needed for "os2emx.h"; if this is defined,
31 // emx will define PSZ as _signed_ char, otherwise
32 // as unsigned char
33
34#define INCL_DOSFILEMGR
35#include <os2.h>
36
37#include <stdlib.h>
38#include <string.h>
39
40#include "setup.h"
41
42#define SYSLEVEL_PRIVATE
43#include "helpers\level.h"
44
45// redefine the FIELDOFFSET macro; the one
46// in the OS/2 header files doesn't work with C++
47#undef FIELDOFFSET
48#define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
49
50/*
51 *@@category: Helpers\Control program helpers\SYSLEVEL parsing
52 */
53
54/* ******************************************************************
55 *
56 * Interface
57 *
58 ********************************************************************/
59
60/*
61 *@@ lvlOpenLevelFile:
62 * finds, opens, or creates a SYSLEVEL file. *phFile
63 * receives the DosOpen file handle, which can then be
64 * passed to lvlQueryLevelFileData and such. Alternatively,
65 * you can use DosOpen directly.
66 *
67 * ulOpenMode can be:
68 *
69 * -- OLF_OPEN:
70 * open the specified file. The default behavior is to scan
71 * the current disk, starting from the current directory.
72 * It returns the first SYSLEVEL file whose extension
73 * matches pszName. You can override this by
74 * combining OLF_OPEN with OLF_SCANDISK or
75 * OLF_CHECKID.
76 *
77 * -- OLF_SCANDISKS:
78 * scans all disks (starting from C:). Use this flag to
79 * modify the default OLF_OPEN behavior.
80 *
81 * -- OLF_CHECKID:
82 * finds file(s) whose ID matches the specified one. Use
83 * this flag to override the default OLF_OPEN behavior.
84 *
85 * -- OLF_CREATE:
86 * creates the specified file in the current directory. A
87 * valid pszName and ID should be provided.
88 */
89
90APIRET lvlOpenLevelFile(PSZ pszName, // in: syslevel file name extension
91 PHFILE phFile, // out: Dos file handle
92 ULONG ulOpenMode, // in: OLF_* flags
93 PSZ pszCID) // in: if OLF_CHECKID is specified, the ID
94{
95 APIRET rc = 0;
96 ULONG ulAction;
97 CHAR achFileName[CCHMAXPATHCOMP];
98
99 switch (ulOpenMode)
100 {
101 case OLF_OPEN:
102 case OLF_OPEN | OLF_CHECKID:
103 if (pszName || pszCID)
104 {
105 rc = _findsyslevelfile(pszName, pszCID, achFileName);
106
107 if (rc == 18)
108 rc = _searchsubdirs(pszName, pszCID, achFileName);
109
110 if (rc == 0)
111 rc = DosOpen(achFileName,
112 phFile,
113 &ulAction,
114 0,
115 FILE_NORMAL,
116 FILE_OPEN,
117 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE,
118 0);
119
120 if (rc == 18)
121 rc = 2;
122 }
123 else
124 rc = ERROR_INVALID_PARAMETER;
125 break;
126
127 case OLF_SCANDISKS:
128 case OLF_SCANDISKS | OLF_CHECKID:
129 case OLF_SCANDISKS | OLF_OPEN:
130 case OLF_SCANDISKS | OLF_OPEN | OLF_CHECKID:
131 if (pszName || pszCID)
132 {
133 ULONG ulDrive, ulDriveMap, ulCurrent, ulFound = 0;
134
135 rc = DosQueryCurrentDisk(&ulDrive, &ulDriveMap);
136 ulCurrent = _firstdrive(ulDriveMap);
137
138 while (ulCurrent && !ulFound)
139 {
140 rc = _findsyslevelfile(pszName, pszCID, achFileName);
141 if (rc == 18)
142 rc = _searchsubdirs(pszName, pszCID, achFileName);
143
144 if (rc == 0)
145 {
146 ulFound = 1;
147
148 rc = DosOpen(achFileName,
149 phFile,
150 &ulAction,
151 0,
152 FILE_NORMAL,
153 FILE_OPEN,
154 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE,
155 0);
156 }
157 else
158 ulCurrent = _nextdrive(ulDriveMap, ulCurrent);
159 }
160
161 DosSetDefaultDisk(ulDrive);
162 if (ulFound == 0)
163 rc = 2;
164 }
165 else
166 rc = ERROR_INVALID_PARAMETER;
167 break;
168
169 case OLF_CREATE:
170 if (pszName && pszCID)
171 {
172 SYSLEVELHEADER slh;
173 SYSLEVELDATA sld;
174
175 strcat(strcpy(achFileName, "syslevel."), pszName);
176
177 rc = DosOpen(achFileName,
178 phFile,
179 &ulAction,
180 0,
181 FILE_NORMAL,
182 FILE_CREATE,
183 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE,
184 0);
185
186 slh.h_magic[0] = slh.h_magic[1] = 0xFF;
187 strcpy((PSZ)slh.h_name, "SYSLEVEL");
188 for (ulAction = 0; ulAction < sizeof(slh.h_reserved1); ulAction++)
189 slh.h_reserved1[ulAction] = 0;
190 slh.h_updated = 0;
191 for (ulAction = 0; ulAction < sizeof(slh.h_reserved2); ulAction++)
192 slh.h_reserved2[ulAction] = 0;
193 slh.h_data = sizeof(SYSLEVELHEADER);
194
195 if (rc == 0)
196 rc = _writesyslevelheader(*phFile, &slh);
197
198 memset(&sld, 0, sizeof(sld));
199 sld.d_kind[0] = SLK_STANDARD;
200 sld.d_reserved3 = sld.d_reserved4 = 0x5F;
201 memcpy(sld.d_cid, pszCID, sizeof(sld.d_cid));
202
203 if (rc == 0)
204 rc = DosWrite(*phFile, &sld, sizeof(SYSLEVELDATA), &ulAction);
205 }
206 else
207 rc = ERROR_INVALID_PARAMETER;
208 break;
209 default:
210 rc = ERROR_INVALID_PARAMETER;
211 break;
212 }
213
214 return rc;
215}
216
217/*
218 *@@ lvlQueryLevelFile:
219 * finds all SYSLEVEL files on the system and
220 * writes them to pBuffer.
221 */
222
223APIRET lvlQueryLevelFile(PSZ pszName,
224 PSZ pszCID,
225 PVOID pBuffer,
226 ULONG ulBufSize)
227{
228 ULONG ulDrive, ulDriveMap, ulCurrent;
229 CHAR achFileName[CCHMAXPATHCOMP];
230 APIRET rc = DosQueryCurrentDisk(&ulDrive, &ulDriveMap);
231
232 strcat(strcpy(achFileName, "syslevel."),
233 (pszName == NULL) ? (PSZ) "???" : pszName);
234 memset(pBuffer, 0, ulBufSize);
235
236 ulCurrent = _firstdrive(ulDriveMap);
237
238 while (ulCurrent && (rc == 0))
239 {
240 rc = _findallsyslevelfiles(achFileName, pszCID, &pBuffer, &ulBufSize);
241
242 if (rc == 0)
243 ulCurrent = _nextdrive(ulDriveMap, ulCurrent);
244 }
245
246 if (rc == 0)
247 rc = DosSetDefaultDisk(ulDrive);
248
249 return rc;
250}
251
252/*
253 *@@ lvlQueryLevelFileData:
254 * parses syslevel data from a SYSLEVEL file previously
255 * opened with lvlOpenLevelFile. Alternatively, you can
256 * open the SYSLEVEL file directly using DosOpen.
257 *
258 * ulWhat can be:
259 *
260 * -- QLD_MAJORVERSION
261 * Query (or update) the major version field. It's a
262 * one-character field. It should be in the range '0'-'9'.
263 * The value is placed in (or taken from) the first
264 * character of pBuffer. (Buffer size should be at least 1.)
265 *
266 * -- QLD_MINORVERSION
267 * Query (or update) the minor version field. It's a
268 * two-character field. It should be in range '00'-'99'. The
269 * value is placed in (or taken from) the first two chars
270 * of pBuffer. (Buffer size should be at least 2.)
271 *
272 * -- QLD_REVISION
273 * Query (or update) the revision field. It's should fit in
274 * a character. If it's '0', there's no revision available. It
275 * can be a letter as well as a digit. The value is placed
276 * in (or taken from) the first character of pBuffer.
277 * (Buffer size should be at least 1.)
278 *
279 * -- QLD_KIND
280 * Query (or update) the kind field. The value is placed
281 * in (or taken from) the first character of *pBuffer.
282 * (Buffer size should be at least 1.)
283 *
284 * -- QLD_CURRENTCSD
285 * Query (or update) the current CSD level (when you
286 * update this field, its old value is copied to the old
287 * CSD level field). It's a seven-character field, and it
288 * does not have to be null-terminated. The value is
289 * placed in (or taken from) the first seven characters of
290 * pBuffer. (Buffer size should be at least 7.)
291 *
292 * -- QLD_PREVIOUSCSD
293 * Query the previous CSD level. You can't update this
294 * field. The value is placed in the first seven chars of
295 * pBuffer. (Buffer size should be at least 7.)
296 * Note: CSD levels are not null-terminated. Be careful
297 * when using such a returned value.
298 *
299 * -- QLD_TITLE
300 * Query (or update) the component title field. It's an
301 * eighty-character string (required ending null
302 * included). The value is placed in (or taken from) the
303 * first eighty characters of pBuffer. On input, the buffer
304 * size should be at least 80. On output, the buffer size
305 * can exceed 80, but the written string is truncated
306 * (and null-terminated) to eighty characters.
307 *
308 * -- QLD_ID
309 * Query (or update) the component ID field. It's a
310 * nine-character field. It does not have to be
311 * null-terminated. The value is placed in (or taken
312 * from) the first nine characters of pBuffer. (Buffer size
313 * should be at least 9.)
314 * Note: IDs are not null-terminated. Be careful when
315 * using such a returned value.
316 *
317 * -- QLD_TYPE
318 * Query (or update) the component type field.
319 */
320
321APIRET lvlQueryLevelFileData(HFILE hFile, // in: file handle returned by lvlOpenLevelFile
322 ULONG ulWhat, // in: QLD* flags
323 PVOID pBuffer, // in/out: data
324 ULONG ulBufSize, // in: sizeof(*pBuffer)
325 PULONG pulSize) // out: size required if
326 // ERROR_INSUFFICIENT_BUFFER is returned;
327 // otherwise bytes written
328{
329 APIRET rc = _locatesysleveldata(hFile);
330 PSYSLEVELDATA psld = _allocsysleveldata(hFile);
331
332 if (rc == 0)
333 rc = pBuffer ? rc : ERROR_INVALID_PARAMETER;
334 if (rc == 0)
335 rc = _readsysleveldata(hFile, psld);
336
337 if (rc == 0)
338 switch (ulWhat)
339 {
340 case QLD_MAJORVERSION:
341 if (ulBufSize >= 1)
342 _achBuffer[0] = '0' + (psld->d_version[0] >> 4);
343 else
344 rc = ERROR_INSUFFICIENT_BUFFER;
345 _setsize(1);
346 break;
347 case QLD_MINORVERSION:
348 if (ulBufSize >= 2)
349 {
350 _achBuffer[0] = '0' + (psld->d_version[0] & 0x0F);
351 _achBuffer[1] = '0' + psld->d_version[1];
352 }
353 else
354 rc = ERROR_INSUFFICIENT_BUFFER;
355 _setsize(2);
356 break;
357 case QLD_REVISION:
358 if (ulBufSize >= 1)
359 _achBuffer[0] = '0' + psld->d_revision[0];
360 else
361 rc = ERROR_INSUFFICIENT_BUFFER;
362 _setsize(1);
363 break;
364 case QLD_KIND:
365 _getfield(d_kind);
366 break;
367 case QLD_CURRENTCSD:
368 _getfield(d_clevel);
369 break;
370 case QLD_PREVIOUSCSD:
371 _getfield(d_plevel);
372 break;
373 case QLD_TITLE:
374 _getfield(d_title);
375 break;
376 case QLD_ID:
377 _getfield(d_cid);
378 break;
379 case QLD_TYPE:
380 if (ulBufSize >= strlen((PSZ)psld->d_type))
381 memcpy(pBuffer, psld->d_type, strlen((PSZ)psld->d_type));
382 else
383 rc = ERROR_INSUFFICIENT_BUFFER;
384 _setsize(strlen((PSZ)psld->d_type));
385 break;
386 default:
387 rc = ERROR_INVALID_PARAMETER;
388 break;
389 }
390
391 _freesysleveldata(psld);
392
393 return rc;
394}
395
396/*
397 *@@ lvlWriteLevelFileData:
398 * writes data to a SYSLEVEL file.
399 */
400
401APIRET lvlWriteLevelFileData(HFILE hFile,
402 ULONG ulWhat,
403 PVOID pBuffer,
404 ULONG ulBufSize,
405 PULONG pulSize)
406{
407 APIRET rc = _locatesysleveldata(hFile);
408 PSYSLEVELDATA psld = _allocsysleveldata(hFile);
409
410 if (rc == 0)
411 rc = pBuffer ? rc : ERROR_INVALID_PARAMETER;
412 if (rc == 0)
413 rc = _readsysleveldata(hFile, psld);
414
415 if (rc == 0)
416 switch (ulWhat)
417 {
418 case QLD_MAJORVERSION:
419 if (ulBufSize >= 1)
420 {
421 psld->d_version[0] &= 0x0F;
422 psld->d_version[0] |= (_achBuffer[0] - '0') << 4;
423 }
424 else
425 rc = ERROR_INSUFFICIENT_BUFFER;
426 _setsize(1);
427 break;
428 case QLD_MINORVERSION:
429 if (ulBufSize >= 2)
430 {
431 psld->d_version[0] &= 0xF0;
432 psld->d_version[0] |= (_achBuffer[0] - '0') && 0x0F;
433 psld->d_version[1] = _achBuffer[1] - '0';
434 }
435 else
436 rc = ERROR_INSUFFICIENT_BUFFER;
437 _setsize(2);
438 break;
439 case QLD_REVISION:
440 _setfield(d_revision);
441 break;
442 case QLD_KIND:
443 _setfield(d_kind);
444 break;
445 case QLD_CURRENTCSD:
446 memcpy(psld->d_plevel, psld->d_clevel, sizeof(psld->d_plevel));
447 _setfield(d_clevel);
448 break;
449 case QLD_TITLE:
450 memcpy(psld->d_title, pBuffer, min(ulBufSize, sizeof(psld->d_title)));
451 _setsize(min(ulBufSize, sizeof(psld->d_title)));
452 break;
453 case QLD_ID:
454 _setfield(d_cid);
455 break;
456 case QLD_TYPE:
457 break;
458 default:
459 rc = ERROR_INVALID_PARAMETER;
460 break;
461 }
462
463 if (rc == 0)
464 rc = _locatesysleveldata(hFile);
465 if (rc == 0)
466 rc = _writesysleveldata(hFile, psld);
467
468 _freesysleveldata(psld);
469
470 return rc;
471}
472
473/* ******************************************************************
474 *
475 * Local helper functions
476 *
477 ********************************************************************/
478
479/*
480 * _readsysleveldata:
481 *
482 */
483
484static APIRET _readsysleveldata(HFILE hFile,
485 PSYSLEVELDATA psld)
486{
487 ULONG ulSize;
488
489 return DosRead(hFile, psld, sizeof(SYSLEVELDATA), &ulSize);
490}
491
492/*
493 * _writesysleveldata:
494 *
495 */
496
497static APIRET _writesysleveldata(HFILE hFile,
498 PSYSLEVELDATA psld)
499{
500 ULONG ulSize;
501
502 return DosWrite(hFile, psld, sizeof(SYSLEVELDATA), &ulSize);
503}
504
505/*
506 * _locatesysleveldata:
507 *
508 */
509
510static APIRET _locatesysleveldata(HFILE hFile)
511{
512 ULONG ulPos, ulData;
513 APIRET rc = DosSetFilePtr(hFile,
514 FIELDOFFSET(SYSLEVELHEADER, h_data),
515 FILE_BEGIN,
516 &ulPos);
517
518 rc = rc ? rc : DosRead(hFile, &ulData, sizeof(ulData), &ulPos);
519
520 return rc ? rc : DosSetFilePtr(hFile, ulData, FILE_BEGIN, &ulPos);
521}
522
523/*
524 * _allocsysleveldata:
525 *
526 */
527
528static PSYSLEVELDATA _allocsysleveldata(HFILE hFile)
529{
530 return (PSYSLEVELDATA) malloc(sizeof(SYSLEVELDATA));
531}
532
533/*
534 * _freesysleveldata:
535 *
536 */
537
538static VOID _freesysleveldata(PSYSLEVELDATA psld)
539{
540 if (psld)
541 free(psld);
542}
543
544/*
545 * _writesyslevelheader:
546 *
547 */
548
549static APIRET _writesyslevelheader(HFILE hFile,
550 PSYSLEVELHEADER pslh)
551{
552 ULONG ulSize;
553
554 return DosWrite(hFile, pslh, sizeof(SYSLEVELHEADER), &ulSize);
555}
556
557/*
558 * _isasyslevelfile:
559 *
560 */
561
562static BOOL _isasyslevelfile(PSZ pszFile,
563 PSZ pszCID)
564{
565 HFILE hFile;
566 ULONG ulAction;
567 SYSLEVELHEADER slh;
568 APIRET rc = DosOpen(pszFile,
569 &hFile,
570 &ulAction,
571 0,
572 FILE_NORMAL,
573 FILE_OPEN,
574 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
575 0);
576
577 if (rc == 0)
578 rc = DosRead(hFile, &slh, sizeof(slh), &ulAction);
579
580 ulAction = (slh.h_magic[0] == 0xFF) && (slh.h_magic[1] == 0xFF);
581 if (ulAction)
582 ulAction = strcmp((PSZ)slh.h_name, "SYSLEVEL") == 0;
583 if (ulAction)
584 if (pszCID)
585 {
586 CHAR achCID[9];
587 ULONG ulCID;
588
589 rc = lvlQueryLevelFileData(hFile, QLD_ID, achCID, 9, &ulCID);
590 ulAction = (strcmp(achCID, pszCID) == 0);
591 }
592
593 rc = DosClose(hFile);
594
595 return ulAction;
596}
597
598/*
599 * _getfullname:
600 *
601 */
602
603static APIRET _getfullname(PVOID pBuffer,
604 PSZ pszFileName)
605{
606 ULONG ulDrive, ulDriveMap, ulBufSize = CCHMAXPATHCOMP;
607 APIRET rc = DosQueryCurrentDisk(&ulDrive, &ulDriveMap);
608
609 _achBuffer[0] = '@' + ulDrive;
610 _achBuffer[1] = ':';
611 _achBuffer[2] = '\\';
612 rc = DosQueryCurrentDir(0, _achBuffer + 3, &ulBufSize);
613 strcat(strcat((PSZ)pBuffer, "\\"), pszFileName);
614
615 return rc;
616}
617
618/*
619 * _findsyslevelfile:
620 *
621 */
622
623static APIRET _findsyslevelfile(PSZ pszName,
624 PSZ pszCID,
625 PVOID pBuffer)
626{
627 HDIR hDirHandle = HDIR_CREATE;
628 FILEFINDBUF3 ffb;
629 ULONG ulCount = 1, ulFound = 0;
630 CHAR achFileName[CCHMAXPATHCOMP] = "syslevel.";
631 APIRET rc = 0;
632
633 if (pszName)
634 strcat(achFileName, pszName);
635 else
636 strcat(achFileName, "???");
637
638 rc = DosFindFirst(achFileName,
639 &hDirHandle,
640 FILE_NORMAL,
641 (PVOID) & ffb,
642 sizeof(ffb),
643 &ulCount,
644 FIL_STANDARD);
645
646 while ((!ulFound) && (rc == 0))
647 {
648 if (_isasyslevelfile(ffb.achName, pszCID))
649 {
650 _getfullname(pBuffer, ffb.achName);
651 ulFound = 1;
652 break;
653 }
654
655 rc = DosFindNext(hDirHandle, (PVOID) & ffb, sizeof(ffb), &ulCount);
656 }
657
658 if ((rc == 0) || (rc == 18))
659 rc = DosFindClose(hDirHandle);
660
661 return ulFound ? 0 : 18;
662}
663
664/*
665 * _findallsyslevelfiles:
666 *
667 */
668
669static APIRET _findallsyslevelfiles(PSZ achFileName,
670 PSZ pszCID,
671 PPVOID ppBuffer,
672 PULONG pulBufSize)
673{
674 HDIR hDirHandle = HDIR_CREATE;
675 FILEFINDBUF3 ffb;
676 ULONG ulCount = 1, ulSize;
677 APIRET rc = DosFindFirst(achFileName,
678 &hDirHandle,
679 FILE_NORMAL,
680 (PVOID) & ffb,
681 sizeof(ffb),
682 &ulCount,
683 FIL_STANDARD);
684
685 while (rc == 0)
686 {
687 if (_isasyslevelfile(ffb.achName, pszCID))
688 {
689 CHAR achBuf[CCHMAXPATHCOMP];
690
691 _getfullname(achBuf, ffb.achName);
692 ulSize = strlen(achBuf);
693 if ((*pulBufSize) > ulSize)
694 {
695 *pulBufSize -= ulSize + 1;
696 memcpy(*ppBuffer, achBuf, ulSize);
697 *ppBuffer = ((CHAR *) (*ppBuffer)) + ulSize + 1;
698 }
699 else
700 rc = ERROR_INSUFFICIENT_BUFFER;
701 }
702
703 if (rc == 0)
704 rc = DosFindNext(hDirHandle, (PVOID) & ffb, sizeof(ffb), &ulCount);
705 }
706
707 if ((rc == 0) || (rc == 18))
708 {
709 rc = DosFindClose(hDirHandle);
710 if (rc == 6)
711 rc = 0;
712 }
713
714 hDirHandle = HDIR_CREATE;
715 if (rc == 0)
716 rc = DosFindFirst("*",
717 &hDirHandle,
718 MUST_HAVE_DIRECTORY,
719 (PVOID) & ffb,
720 sizeof(ffb),
721 &ulCount,
722 FIL_STANDARD);
723
724 while (rc == 0)
725 {
726 if (ffb.achName[0] == '.' &&
727 (ffb.achName[1] == 0 || (ffb.achName[1] == '.' && ffb.achName[2] == 0)))
728 {
729 }
730 else
731 {
732 rc = DosSetCurrentDir(ffb.achName);
733
734 if (rc == 0)
735 rc = _findallsyslevelfiles(achFileName, pszCID, ppBuffer, pulBufSize);
736
737 if ((rc == 0) || (rc == 18))
738 rc = DosSetCurrentDir("..");
739 }
740
741 if (rc == 0)
742 rc = DosFindNext(hDirHandle, (PVOID) & ffb, sizeof(ffb), &ulCount);
743 }
744
745 if ((rc == 0) || (rc == 18))
746 {
747 rc = DosFindClose(hDirHandle);
748 if (rc == 6)
749 rc = 0;
750 }
751
752 return rc;
753}
754
755/*
756 * _searchsubdirs:
757 *
758 */
759
760static APIRET _searchsubdirs(PSZ pszName,
761 PSZ pszCID,
762 PVOID pBuffer)
763{
764 HDIR hDirHandle = HDIR_CREATE;
765 FILEFINDBUF3 ffb;
766 ULONG ulCount = 1, ulFound = 0;
767 APIRET rc = DosFindFirst("*",
768 &hDirHandle,
769 MUST_HAVE_DIRECTORY,
770 (PVOID) & ffb,
771 sizeof(ffb),
772 &ulCount,
773 FIL_STANDARD);
774
775 while ((!ulFound) && (rc == 0))
776 {
777 if (ffb.achName[0] == '.' &&
778 (ffb.achName[1] == 0 || (ffb.achName[1] == '.' && ffb.achName[2] == 0)))
779 {
780 }
781 else
782 {
783 rc = DosSetCurrentDir(ffb.achName);
784
785 if (rc == 0)
786 rc = _findsyslevelfile(pszName, pszCID, pBuffer);
787
788 if (rc == 18)
789 rc = _searchsubdirs(pszName, pszCID, pBuffer);
790
791 if (rc == 0)
792 ulFound = 1;
793
794 if ((rc == 0) || (rc == 18))
795 rc = DosSetCurrentDir("..");
796 }
797
798 if ((!ulFound) && (rc == 0))
799 rc = DosFindNext(hDirHandle, (PVOID) & ffb, sizeof(ffb), &ulCount);
800 }
801
802 rc = DosFindClose(hDirHandle);
803
804 return ulFound ? 0 : 18;
805}
806
807/*
808 * _firstdrive:
809 *
810 */
811
812static ULONG _firstdrive(ULONG ulDriveMap)
813{
814 return _nextdrive(ulDriveMap, 2);
815}
816
817/*
818 * _nextdrive:
819 *
820 */
821
822static ULONG _nextdrive(ULONG ulDriveMap,
823 ULONG ulCurrent)
824{
825 ULONG ulNext = ulCurrent + 1;
826
827 while (ulNext < 27)
828 if (ulDriveMap & (0x1 << (ulNext - 1)))
829 break;
830 else
831 ulNext++;
832
833 if (ulNext < 27)
834 {
835 DosSetDefaultDisk(ulNext);
836 DosSetCurrentDir("\\");
837 }
838
839 return (ulNext == 27) ? 0 : ulNext;
840}
Note: See TracBrowser for help on using the repository browser.