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

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

Misc helpers updates.

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