source: trunk/src/helpers/wphandle.c@ 108

Last change on this file since 108 was 108, checked in by umoeller, 24 years ago

Lots of updates from the last week for conditional compiles and other stuff.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 29.9 KB
Line 
1
2/*
3 *@@sourcefile wphandle.c:
4 * this file contains the logic for dealing with
5 * those annoying WPS object handles in OS2SYS.INI.
6 * This does not use WPS interfaces, but parses
7 * the profiles directly.
8 *
9 * Usage: All OS/2 programs.
10 *
11 * Function prefixes (new with V0.81):
12 * -- wph* WPS object helper functions
13 *
14 * Thanks go out to Henk Kelder for telling me the
15 * format of the WPS INI data. With V0.9.16, this
16 * file was completely rewritten and no longer uses
17 * his code though.
18 *
19 * Note: Version numbering in this file relates to XWorkplace version
20 * numbering.
21 *
22 *@@header "helpers\wphandle.h"
23 */
24
25/*
26 * This file Copyright (C) 1997-2001 Ulrich M”ller,
27 * This file is part of the "XWorkplace helpers" source package.
28 * This is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published
30 * by the Free Software Foundation, in version 2 as it comes in the
31 * "COPYING" file of the XWorkplace main distribution.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 */
37
38#define OS2EMX_PLAIN_CHAR
39 // this is needed for "os2emx.h"; if this is defined,
40 // emx will define PSZ as _signed_ char, otherwise
41 // as unsigned char
42
43#define INCL_DOSEXCEPTIONS
44#define INCL_DOSPROCESS
45#define INCL_DOSERRORS
46
47#define INCL_WINSHELLDATA
48#include <os2.h>
49
50#include <stdio.h>
51#include <string.h>
52#include <stdlib.h>
53#include <io.h>
54#include <setjmp.h>
55
56#include "setup.h" // code generation and debugging options
57
58#include "helpers\except.h"
59#include "helpers\prfh.h"
60#include "helpers\standards.h"
61#include "helpers\stringh.h"
62#include "helpers\wphandle.h"
63#include "helpers\xstring.h"
64
65/*
66 *@@category: Helpers\PM helpers\Workplace Shell\Handles (OS2SYS.INI)
67 * See wphandle.c.
68 */
69
70/* ******************************************************************
71 *
72 * Load handles functions
73 *
74 ********************************************************************/
75
76/*
77 *@@ wphQueryActiveHandles:
78 * returns the value of PM_Workplace:ActiveHandles
79 * in OS2SYS.INI as a new buffer.
80 *
81 * There are always two buffers in OS2SYS.INI for object
82 * handles, called "PM_Workplace:HandlesX" with "X" either
83 * being "0" or "1".
84 *
85 * It seems that every time the WPS does something in the
86 * handles section, it writes the data to the inactive
87 * buffer first and then makes it the active buffer by
88 * changing the "active handles" key. You can test this
89 * by creating a shadow on your Desktop.
90 *
91 * This returns a new PSZ which the caller must free()
92 * after use.
93 *
94 * This gets called by the one-shot function
95 * wphQueryHandleFromPath.
96 *
97 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
98 */
99
100APIRET wphQueryActiveHandles(HINI hiniSystem,
101 PSZ *ppszActiveHandles)
102{
103 PSZ pszActiveHandles;
104 if (pszActiveHandles = prfhQueryProfileData(hiniSystem,
105 WPINIAPP_ACTIVEHANDLES,
106 WPINIAPP_HANDLESAPP,
107 NULL))
108 {
109 *ppszActiveHandles = pszActiveHandles;
110 return (NO_ERROR);
111 }
112
113 return (ERROR_WPH_NO_ACTIVEHANDLES_DATA);
114}
115
116/*
117 *@@ wphQueryBaseClassesHiwords:
118 * returns the hiwords for the WPS base
119 * classes. Unless the user's system is
120 * really badly configured, this should
121 * set
122 *
123 * -- pusHiwordAbstract to 2;
124 * -- pusHiwordFileSystem to 3.
125 *
126 * Returns:
127 *
128 * -- NO_ERROR
129 *
130 * -- ERROR_WPH_NO_BASECLASS_DATA
131 *
132 * -- ERROR_WPH_INCOMPLETE_BASECLASS_DATA
133 *
134 * This gets called automatically from wphLoadHandles.
135 *
136 *@@added V0.9.16 (2001-10-02) [umoeller]
137 */
138
139APIRET wphQueryBaseClassesHiwords(HINI hiniUser,
140 PUSHORT pusHiwordAbstract,
141 PUSHORT pusHiwordFileSystem)
142{
143 APIRET arc = NO_ERROR;
144
145 // get the index of WPFileSystem from the base classes list...
146 // we need this to determine the hiword for file-system handles
147 // properly. Normally, this should be 3.
148 ULONG cbBaseClasses = 0;
149 PSZ pszBaseClasses;
150 if (pszBaseClasses = prfhQueryProfileData(hiniUser,
151 "PM_Workplace:BaseClass",
152 "ClassList",
153 &cbBaseClasses))
154 {
155 // parse that buffer... these has the base class names,
156 // separated by 0. List is terminated by two zeroes.
157 PSZ pszClassThis = pszBaseClasses;
158 ULONG ulHiwordThis = 1;
159 while ( (*pszClassThis)
160 && (pszClassThis - pszBaseClasses < cbBaseClasses)
161 )
162 {
163 if (!strcmp(pszClassThis, "WPFileSystem"))
164 *pusHiwordFileSystem = ulHiwordThis;
165 else if (!strcmp(pszClassThis, "WPAbstract"))
166 *pusHiwordAbstract = ulHiwordThis;
167
168 ulHiwordThis++;
169 pszClassThis += strlen(pszClassThis) + 1;
170 }
171
172 // now check if we found both
173 if ( (!(*pusHiwordFileSystem))
174 || (!(*pusHiwordAbstract))
175 )
176 arc = ERROR_WPH_INCOMPLETE_BASECLASS_DATA;
177
178 free(pszBaseClasses);
179 }
180 else
181 arc = ERROR_WPH_NO_BASECLASS_DATA;
182
183 return (arc);
184}
185
186/*
187 *@@ wphRebuildNodeHashTable:
188 *
189 * Returns:
190 *
191 * -- NO_ERROR
192 *
193 * -- ERROR_INVALID_PARAMETER
194 *
195 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
196 *
197 *@@added V0.9.16 (2001-10-02) [umoeller]
198 */
199
200APIRET wphRebuildNodeHashTable(PHANDLESBUF pHandlesBuf)
201{
202 APIRET arc = NO_ERROR;
203
204 if ( (!pHandlesBuf)
205 || (!pHandlesBuf->pbData)
206 || (!pHandlesBuf->cbData)
207 )
208 arc = ERROR_INVALID_PARAMETER;
209 else
210 {
211 // start at beginning of buffer
212 PBYTE pCur = pHandlesBuf->pbData + 4;
213 PBYTE pEnd = pHandlesBuf->pbData + pHandlesBuf->cbData;
214
215 memset(pHandlesBuf->NodeHashTable, 0, sizeof(pHandlesBuf->NodeHashTable));
216
217 // now set up hash table
218 while (pCur < pEnd)
219 {
220 if (!memicmp(pCur, "DRIV", 4))
221 {
222 // pCur points to a DRIVE node:
223 // these never have handles, so skip this
224 PDRIV pDriv = (PDRIV)pCur;
225 pCur += sizeof(DRIV) + strlen(pDriv->szName);
226 }
227 else if (!memicmp(pCur, "NODE", 4))
228 {
229 // pCur points to a regular NODE: offset pointer first
230 PNODE pNode = (PNODE)pCur;
231 // store PNODE in hash table
232 pHandlesBuf->NodeHashTable[pNode->usHandle] = pNode;
233 pCur += sizeof (NODE) + pNode->usNameSize;
234 }
235 else
236 {
237 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
238 break;
239 }
240 }
241 }
242
243 if (!arc)
244 pHandlesBuf->fNodeHashTableValid = TRUE;
245
246 return (arc);
247}
248
249/*
250 *@@ wphLoadHandles:
251 * returns a HANDLESBUF structure which will hold
252 * all the handles from OS2SYS.INI. In addition,
253 * this calls wphQueryBaseClassesHiwords and puts
254 * the hiwords for WPAbstract and WPFileSystem into
255 * the HANDLESBUF as well.
256 *
257 * Prerequisite before using any of the other wph*
258 * functions.
259 *
260 * Call wphFreeHandles to free all data allocated
261 * by this function.
262 *
263 * Returns:
264 *
265 * -- NO_ERROR
266 *
267 * -- ERROR_NOT_ENOUGH_MEMORY
268 *
269 * -- ERROR_INVALID_PARAMETER
270 *
271 * -- ERROR_WPH_NO_HANDLES_DATA: cannot read handle blocks.
272 *
273 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: cannot read handle blocks.
274 *
275 *@@added V0.9.16 (2001-10-02) [umoeller]
276 */
277
278APIRET wphLoadHandles(HINI hiniUser, // in: HINI_USER or other INI handle
279 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
280 const char *pcszActiveHandles,
281 PHANDLESBUF *ppHandlesBuf)
282{
283 APIRET arc = NO_ERROR;
284
285 if (!ppHandlesBuf)
286 arc = ERROR_INVALID_PARAMETER;
287 else
288 {
289 PSZ pszKeysList;
290 if (!(arc = prfhQueryKeysForApp(hiniSystem,
291 pcszActiveHandles,
292 &pszKeysList)))
293 {
294 PHANDLESBUF pReturn = NULL;
295
296 ULONG ulHighestBlock = 0,
297 ul,
298 cbTotal;
299 PBYTE pbData;
300
301 const char *pKey2 = pszKeysList;
302 while (*pKey2)
303 {
304 if (!memicmp((PVOID)pKey2, "BLOCK", 5))
305 {
306 ULONG ulBlockThis = atoi(pKey2 + 5);
307 if (ulBlockThis > ulHighestBlock)
308 ulHighestBlock = ulBlockThis;
309 }
310
311 pKey2 += strlen(pKey2)+1; // next key
312 }
313
314 free(pszKeysList);
315
316 if (!ulHighestBlock)
317 arc = ERROR_WPH_NO_HANDLES_DATA;
318 else
319 {
320 // now go read the data
321 // (BLOCK1, BLOCK2, ..., BLOCKn)
322 cbTotal = 0;
323 pbData = NULL;
324 for (ul = 1;
325 ul <= ulHighestBlock;
326 ul++)
327 {
328 ULONG cbBlockThis;
329 CHAR szBlockThis[10];
330 sprintf(szBlockThis, "BLOCK%d", ul);
331 if (!PrfQueryProfileSize(hiniSystem,
332 (PSZ)pcszActiveHandles,
333 szBlockThis,
334 &cbBlockThis))
335 {
336 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
337 break;
338 }
339 else
340 {
341 ULONG cbTotalOld = cbTotal;
342 cbTotal += cbBlockThis;
343 if (!(pbData = realloc(pbData, cbTotal)))
344 // on first call, pbData is NULL and this
345 // behaves like malloc()
346 {
347 arc = ERROR_NOT_ENOUGH_MEMORY;
348 break;
349 }
350
351 if (!PrfQueryProfileData(hiniSystem,
352 (PSZ)pcszActiveHandles,
353 szBlockThis,
354 pbData + cbTotalOld,
355 &cbBlockThis))
356 {
357 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
358 break;
359 }
360 }
361 }
362 }
363
364 if (!arc)
365 {
366 // all went OK:
367 if (pReturn = NEW(HANDLESBUF))
368 {
369 ZERO(pReturn);
370
371 pReturn->pbData = pbData;
372 pReturn->cbData = cbTotal;
373
374 // and load the hiwords too
375 if (!(arc = wphQueryBaseClassesHiwords(hiniUser,
376 &pReturn->usHiwordAbstract,
377 &pReturn->usHiwordFileSystem)))
378 *ppHandlesBuf = pReturn;
379 }
380 else
381 arc = ERROR_NOT_ENOUGH_MEMORY;
382 }
383
384 if (arc)
385 // error:
386 wphFreeHandles(&pReturn);
387 }
388 }
389
390 return (arc);
391}
392
393/*
394 *@@ wphFreeHandles:
395 * frees all data allocated by wphLoadHandles
396 * and sets *ppHandlesBuf to NULL, for safety.
397 *
398 *@@added V0.9.16 (2001-10-02) [umoeller]
399 */
400
401APIRET wphFreeHandles(PHANDLESBUF *ppHandlesBuf)
402{
403 APIRET arc = NO_ERROR;
404
405 if (ppHandlesBuf && *ppHandlesBuf)
406 {
407 PBYTE pbData;
408 if (pbData = (*ppHandlesBuf)->pbData)
409 free(pbData);
410
411 free(*ppHandlesBuf);
412 *ppHandlesBuf = NULL;
413 }
414 else
415 arc = ERROR_INVALID_PARAMETER;
416
417 return (arc);
418}
419
420/*
421 *@@ wphReadAllBlocks:
422 * this reads all the BLOCK's in the active handles
423 * section in OS2SYS.INI into one common buffer, for
424 * which sufficient memory is allocated.
425 *
426 * Each of these blocks is a maximum of 64 KB, hell
427 * knows why, maybe the INIs can't handle more. This
428 * func combines all the BLOCK's into one buffer anyways,
429 * which can then be searched.
430 *
431 * Use wphQueryActiveHandles to pass the active handles
432 * section to this function.
433 *
434 * This gets called by the one-shot function
435 * wphQueryHandleFromPath.
436 */
437
438/* BOOL wphReadAllBlocks(HINI hiniSystem, // in: can be HINI_USER or HINI_SYSTEM
439 PSZ pszActiveHandles, // in: active handles section
440 PBYTE* ppBlock, // in/out: pointer to buffer, which
441 // will point to the allocated
442 // memory afterwards
443 PULONG pulSize) // out: size of the allocated buffer
444{
445 PBYTE pbAllBlocks,
446 pszBlockName,
447 p;
448 ULONG ulBlockSize;
449 ULONG ulTotalSize;
450 BYTE rgfBlock[100];
451 BYTE szAppName[10];
452 USHORT usBlockNo;
453
454 pbAllBlocks = wphEnumProfileKeys(hiniSystem, pszActiveHandles, &ulBlockSize);
455 if (!pbAllBlocks)
456 return FALSE;
457
458 // query size of all individual blocks and calculate total
459 memset(rgfBlock, 0, sizeof rgfBlock);
460 ulTotalSize = 0L;
461 pszBlockName = pbAllBlocks;
462 while (*pszBlockName)
463 {
464 if (!memicmp(pszBlockName, "BLOCK", 5))
465 {
466 usBlockNo = atoi(pszBlockName + 5);
467 if (usBlockNo < 100)
468 {
469 rgfBlock[usBlockNo] = TRUE;
470
471 if (!PrfQueryProfileSize(hiniSystem,
472 pszActiveHandles,
473 pszBlockName,
474 &ulBlockSize))
475 {
476 free(pbAllBlocks);
477 return FALSE;
478 }
479 ulTotalSize += ulBlockSize;
480 }
481 }
482 pszBlockName += strlen(pszBlockName) + 1;
483 }
484
485 // *pulSize now contains the total size of all blocks
486 *ppBlock = (PBYTE)malloc(ulTotalSize);
487 if (!(*ppBlock))
488 {
489 free(pbAllBlocks);
490 return FALSE;
491 }
492
493 // now get all blocks into the memory we allocated
494 p = *ppBlock;
495 (*pulSize) = 0;
496 for (usBlockNo = 1; usBlockNo < 100; usBlockNo++)
497 {
498 if (!rgfBlock[usBlockNo])
499 break;
500
501 sprintf(szAppName, "BLOCK%u", (UINT)usBlockNo);
502 ulBlockSize = ulTotalSize;
503 if (!PrfQueryProfileData(hiniSystem,
504 pszActiveHandles,
505 szAppName,
506 p,
507 &ulBlockSize))
508 {
509 free(pbAllBlocks);
510 free(*ppBlock);
511 return FALSE;
512 }
513 p += ulBlockSize;
514 (*pulSize) += ulBlockSize;
515 ulTotalSize -= ulBlockSize;
516 }
517
518 free(pbAllBlocks);
519 return TRUE;
520} */
521
522/* ******************************************************************
523 *
524 * Get HOBJECT from filename
525 *
526 ********************************************************************/
527
528/*
529 *@@ wphSearchBufferForHandle:
530 * returns the four-digit object handle which corresponds
531 * to pszFilename, searching pHandlesBuffer. Note that you
532 * must OR the return value with 0x30000 to make this
533 * a valid WPS file-system handle.
534 *
535 * You must pass a handles buffer to this function which
536 * has been filled using wphReadAllBlocks above.
537 *
538 * This gets called by the one-shot function
539 * wphQueryHandleFromPath.
540 */
541
542USHORT wphSearchBufferForHandle(PBYTE pHandlesBuffer, // in: handles buffer (all BLOCK's)
543 ULONG ulBufSize, // in: sizeof(pHandlesBuffer)
544 USHORT usParent, // in: parent NODE ID;
545 // must be 0 initially
546 PSZ pszFilename) // in: fully qlf'd filename to search for
547{
548 PDRIV pDriv;
549 PNODE pNode;
550 PBYTE pCur; // current
551 PBYTE p,
552 pEnd; // *end of buffer
553 USHORT usPartSize;
554
555 // _Pmpf(("Entering wphSearchBufferForHandle for %s", pszFilename));
556
557 // The composed BLOCKs in the handles buffer make up a tree of
558 // DRIVE and NODE structures (see wphandle.h). Each NODE stands
559 // for either a directory or a file. (We don't care about the
560 // DRIVE structures because the root directory gets a NODE also.)
561 // Each NODE contains the non-qualified file name, an object ID,
562 // and the object ID of its parent NODE.
563 // We can thus work our way through the buffer by splitting the
564 // fully qualified filename that we're searching for into the
565 // different directory names and, each time, searching for the
566 // corresponding NODE. If we have found that, we go for the next.
567 // Example for C:\OS2\E.EXE:
568 // 1) first search for the "C:" NODE
569 // 2) then find the "OS2" node which has "C" as its parent NODE
570 // (we do this by comparing the parent object handles)
571 // 3) then find the "E.EXE" NODE the same way
572 // The "E.EXE" NODE then has the object handle we're looking for.
573
574 // So first find the length of the first filename part (which
575 // should be 2 for the drive letter, "C:")
576 p = strchr(pszFilename, '\\');
577 if (p)
578 // backslash found:
579 usPartSize = p - pszFilename; // extract first part
580 else
581 usPartSize = strlen(pszFilename);
582
583 // now set the pointer for the end of the BLOCKs buffer
584 pEnd = pHandlesBuffer + ulBufSize;
585
586 // pCur is our variable pointer where we're at now; there
587 // is some offset of 4 bytes at the beginning (duh)
588 pCur = pHandlesBuffer + 4;
589
590 // _Pmpf((" Searching for: %s, usPartSize: %d", pszFilename, usPartSize));
591
592 // go!
593 while (pCur < pEnd)
594 {
595 // the first four chars tell us whether it's
596 // a DRIVE or a NODE structure
597 if (!memicmp(pCur, "DRIV", 4))
598 {
599 // pCur points to a DRIVE node:
600 // we don't care about these, because the root
601 // directory has a real NODE too, so we just
602 // skip this
603 pDriv = (PDRIV)pCur;
604 pCur += sizeof(DRIV) + strlen(pDriv->szName);
605 }
606 else if (!memicmp(pCur, "NODE", 4))
607 {
608 // pCur points to a regular NODE: offset pointer first
609 pNode = (PNODE)pCur;
610 pCur += sizeof (NODE) + pNode->usNameSize;
611
612 // does the NODE have the same parent that we
613 // are currently searching for? This is "0"
614 // for root directories (and initially for us
615 // too)
616 if (usParent == pNode->usParentHandle)
617 {
618 // yes:
619 // _Pmpf((" found matching parents (%lX): %s", usParent, pNode->szName));
620
621 // does the NODE have the same partname length?
622 if (pNode->usNameSize == usPartSize)
623 {
624 // yes:
625 // _Pmpf((" found matching partnames sizes: %d", pNode->usNameSize));
626
627 // do the partnames match too?
628 if (memicmp(pszFilename, pNode->szName, usPartSize) == 0)
629 {
630 // OK!! proper NODE found!
631 // _Pmpf((" FOUND %s!!", pNode->szName));
632
633 // now check if this was the last NODE
634 // we were looking for
635 if (strlen(pszFilename) == usPartSize)
636 // yes: return ID
637 return (pNode->usHandle);
638
639 // else: update our status;
640 // get next partname
641 pszFilename += usPartSize + 1;
642 // calc next partname length
643 p = strchr(pszFilename, '\\');
644 if (p)
645 usPartSize = p - pszFilename;
646 else
647 usPartSize = strlen(pszFilename);
648
649 // get next parent to search for
650 // (which is the current handle)
651 usParent = pNode->usHandle;
652 }
653 }
654 }
655 }
656 else
657 // neither DRIVE nor NODE: error
658 return (0);
659
660 } // end while
661
662 // not found: end of buffer reached
663 return (0);
664}
665
666/*
667 *@@ wphQueryHandleFromPath:
668 * finds the object handle for the given fully qualified
669 * filename.
670 * This is a one-shot function, using wphQueryActiveHandles,
671 * wphReadAllBlocks, and wphSearchBufferForHandle.
672 *
673 * Returns:
674 *
675 * -- NO_ERROR: *phobj has received the object handle.
676 *
677 * -- ERROR_FILE_NOT_FOUND: file does not exist.
678 *
679 * plus the error codes of the other wph* functions called.
680 *
681 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
682 */
683
684APIRET wphQueryHandleFromPath(HINI hiniUser, // in: HINI_USER or other INI handle
685 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
686 const char *pcszName, // in: fully qlf'd filename
687 HOBJECT *phobj) // out: object handle found if NO_ERROR
688{
689 APIRET arc = NO_ERROR;
690 PVOID pvData;
691
692 TRY_LOUD(excpt1)
693 {
694 // not found there: check the handles then
695 PSZ pszActiveHandles;
696 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
697 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
698 else
699 {
700 PHANDLESBUF pHandlesBuf;
701 if (arc = wphLoadHandles(hiniUser,
702 hiniSystem,
703 pszActiveHandles,
704 &pHandlesBuf))
705 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
706 else
707 {
708 USHORT usObjID;
709 CHAR szFullPath[2*CCHMAXPATH];
710 _fullpath(szFullPath, (PSZ)pcszName, sizeof(szFullPath));
711
712 // search that buffer
713 if (usObjID = wphSearchBufferForHandle(pHandlesBuf->pbData,
714 pHandlesBuf->cbData,
715 0, // usParent
716 szFullPath))
717 // found: OR 0x30000
718 *phobj = usObjID | (pHandlesBuf->usHiwordFileSystem << 16);
719 else
720 arc = ERROR_FILE_NOT_FOUND;
721
722 wphFreeHandles(&pHandlesBuf);
723 }
724
725 free(pszActiveHandles);
726 }
727 }
728 CATCH(excpt1)
729 {
730 arc = ERROR_WPH_CRASHED;
731 } END_CATCH();
732
733 return (arc);
734}
735
736/* ******************************************************************
737 *
738 * Get filename from HOBJECT
739 *
740 ********************************************************************/
741
742/*
743 *@@ ComposeThis:
744 * helper for wphComposePath recursion.
745 *
746 *@@added V0.9.16 (2001-10-02) [umoeller]
747 */
748
749APIRET ComposeThis(PHANDLESBUF pHandlesBuf,
750 USHORT usHandle, // in: handle to search for
751 PXSTRING pstrFilename, // in/out: filename
752 PNODE *ppNode) // out: node found (ptr can be NULL)
753{
754 APIRET arc = NO_ERROR;
755 PNODE pNode;
756 if (pNode = pHandlesBuf->NodeHashTable[usHandle])
757 {
758 // handle exists:
759 if (pNode->usParentHandle)
760 {
761 // node has parent:
762 // recurse first
763 if (arc = ComposeThis(pHandlesBuf,
764 pNode->usParentHandle,
765 pstrFilename,
766 ppNode))
767 {
768 if (arc == ERROR_INVALID_HANDLE)
769 // parent handle not found:
770 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
771 // else leave the APIRET, this might be dangerous
772 }
773 else
774 {
775 // no error:
776 xstrcatc(pstrFilename, '\\');
777 xstrcat(pstrFilename, pNode->szName, pNode->usNameSize);
778 }
779 }
780 else
781 // no parent:
782 xstrcpy(pstrFilename, pNode->szName, pNode->usNameSize);
783 }
784 else
785 arc = ERROR_INVALID_HANDLE;
786
787 if (!arc)
788 if (ppNode)
789 *ppNode = pNode;
790
791 return (arc);
792}
793
794/*
795 *@@ wphComposePath:
796 * returns the fully qualified path name for the specified
797 * file-system handle. This function is very fast because
798 * it uses a hash table for all the handles internally.
799 *
800 * Warning: This calls a helper, which recurses.
801 *
802 * This returns:
803 *
804 * -- NO_ERROR
805 *
806 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: buffer data cannot be parsed.
807 *
808 * -- ERROR_WPH_INVALID_HANDLE: usHandle cannot be found.
809 *
810 * -- ERROR_WPH_INVALID_PARENT_HANDLE: a handle was found
811 * that has a broken parent handle.
812 *
813 * -- ERROR_BUFFER_OVERFLOW: cbFilename is too small to
814 * hold the full path that was composed.
815 *
816 *@@added V0.9.16 (2001-10-02) [umoeller]
817 */
818
819APIRET wphComposePath(PHANDLESBUF pHandlesBuf,
820 USHORT usHandle, // in: loword of handle to search for
821 PSZ pszFilename,
822 ULONG cbFilename,
823 PNODE *ppNode) // out: node found (ptr can be NULL)
824{
825 APIRET arc = NO_ERROR;
826
827 TRY_LOUD(excpt1)
828 {
829 if (!pHandlesBuf->fNodeHashTableValid)
830 arc = wphRebuildNodeHashTable(pHandlesBuf);
831
832 if (!arc)
833 {
834 XSTRING str;
835 xstrInit(&str, CCHMAXPATH);
836 if (!(arc = ComposeThis(pHandlesBuf,
837 usHandle,
838 &str,
839 ppNode)))
840 if (str.ulLength > cbFilename - 1)
841 arc = ERROR_BUFFER_OVERFLOW;
842 else
843 memcpy(pszFilename,
844 str.psz,
845 str.ulLength + 1);
846 }
847 }
848 CATCH(excpt1)
849 {
850 arc = ERROR_WPH_CRASHED;
851 } END_CATCH();
852
853 return (arc);
854}
855
856/*
857 *@@ wphQueryPathFromHandle:
858 * reverse to wphQueryHandleFromPath, this gets the
859 * filename for hObject.
860 * This is a one-shot function, using wphQueryActiveHandles,
861 * wphReadAllBlocks, and wphFindPartName.
862 *
863 * Returns:
864 *
865 * -- NO_ERROR
866 *
867 * -- ERROR_INVALID_HANDLE: hObject is invalid.
868 *
869 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
870 */
871
872APIRET wphQueryPathFromHandle(HINI hiniUser, // in: HINI_USER or other INI handle
873 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
874 HOBJECT hObject, // in: 32-bit object handle
875 PSZ pszFilename, // out: filename, if found
876 ULONG cbFilename) // in: sizeof(*pszFilename)
877{
878 APIRET arc = NO_ERROR;
879
880 TRY_LOUD(excpt1)
881 {
882 PSZ pszActiveHandles;
883 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
884 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
885 else
886 {
887 PHANDLESBUF pHandlesBuf;
888 if (arc = wphLoadHandles(hiniUser,
889 hiniSystem,
890 pszActiveHandles,
891 &pHandlesBuf))
892 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
893 else
894 {
895 // is this really a file-system object?
896 if (HIUSHORT(hObject) == pHandlesBuf->usHiwordFileSystem)
897 {
898 // use loword only
899 USHORT usObjID = LOUSHORT(hObject);
900
901 memset(pszFilename, 0, cbFilename);
902 arc = wphComposePath(pHandlesBuf,
903 usObjID,
904 pszFilename,
905 cbFilename,
906 NULL);
907
908 _Pmpf((__FUNCTION__ ": wphFindPartName returned %d", arc));
909 }
910
911 wphFreeHandles(&pHandlesBuf);
912 }
913
914 free(pszActiveHandles);
915 }
916 }
917 CATCH(excpt1)
918 {
919 arc = ERROR_WPH_CRASHED;
920 } END_CATCH();
921
922 return (arc);
923}
924
925
926
Note: See TracBrowser for help on using the repository browser.