source: branches/branch-1-0/src/helpers/level.c@ 365

Last change on this file since 365 was 222, checked in by umoeller, 23 years ago

Minor adjustments for new static handling.

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