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

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

Executable updates, mostly.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 32.6 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#define INCL_WINNLS
49#include <os2.h>
50
51#include <stdio.h>
52#include <string.h>
53#include <stdlib.h>
54#include <io.h>
55#include <setjmp.h>
56
57#include "setup.h" // code generation and debugging options
58
59#include "helpers\except.h"
60#include "helpers\linklist.h"
61#include "helpers\prfh.h"
62#include "helpers\standards.h"
63#include "helpers\stringh.h"
64#include "helpers\tree.h"
65#include "helpers\xstring.h"
66
67#define INCLUDE_WPHANDLE_PRIVATE
68#include "helpers\wphandle.h"
69
70/*
71 *@@category: Helpers\PM helpers\Workplace Shell\Handles (OS2SYS.INI)
72 * See wphandle.c.
73 */
74
75/* ******************************************************************
76 *
77 * Load handles functions
78 *
79 ********************************************************************/
80
81/*
82 *@@ wphQueryActiveHandles:
83 * returns the value of PM_Workplace:ActiveHandles
84 * in OS2SYS.INI as a new buffer.
85 *
86 * There are always two buffers in OS2SYS.INI for object
87 * handles, called "PM_Workplace:HandlesX" with "X" either
88 * being "0" or "1".
89 *
90 * It seems that every time the WPS does something in the
91 * handles section, it writes the data to the inactive
92 * buffer first and then makes it the active buffer by
93 * changing the "active handles" key. You can test this
94 * by creating a shadow on your Desktop.
95 *
96 * This returns a new PSZ which the caller must free()
97 * after use.
98 *
99 * This gets called by the one-shot function
100 * wphQueryHandleFromPath.
101 *
102 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
103 */
104
105APIRET wphQueryActiveHandles(HINI hiniSystem,
106 PSZ *ppszActiveHandles) // out: active handles string (new buffer)
107{
108 PSZ pszActiveHandles;
109 if (pszActiveHandles = prfhQueryProfileData(hiniSystem,
110 WPINIAPP_ACTIVEHANDLES,
111 WPINIAPP_HANDLESAPP,
112 NULL))
113 {
114 *ppszActiveHandles = pszActiveHandles;
115 return (NO_ERROR);
116 }
117
118 return (ERROR_WPH_NO_ACTIVEHANDLES_DATA);
119}
120
121/*
122 *@@ wphQueryBaseClassesHiwords:
123 * returns the hiwords for the WPS base
124 * classes. Unless the user's system is
125 * really badly configured, this should
126 * set
127 *
128 * -- pusHiwordAbstract to 2;
129 * -- pusHiwordFileSystem to 3.
130 *
131 * Returns:
132 *
133 * -- NO_ERROR
134 *
135 * -- ERROR_WPH_NO_BASECLASS_DATA
136 *
137 * -- ERROR_WPH_INCOMPLETE_BASECLASS_DATA
138 *
139 * This gets called automatically from wphLoadHandles.
140 *
141 *@@added V0.9.16 (2001-10-02) [umoeller]
142 */
143
144APIRET wphQueryBaseClassesHiwords(HINI hiniUser,
145 PUSHORT pusHiwordAbstract,
146 PUSHORT pusHiwordFileSystem)
147{
148 APIRET arc = NO_ERROR;
149
150 // get the index of WPFileSystem from the base classes list...
151 // we need this to determine the hiword for file-system handles
152 // properly. Normally, this should be 3.
153 ULONG cbBaseClasses = 0;
154 PSZ pszBaseClasses;
155 if (pszBaseClasses = prfhQueryProfileData(hiniUser,
156 "PM_Workplace:BaseClass",
157 "ClassList",
158 &cbBaseClasses))
159 {
160 // parse that buffer... these has the base class names,
161 // separated by 0. List is terminated by two zeroes.
162 PSZ pszClassThis = pszBaseClasses;
163 ULONG ulHiwordThis = 1;
164 while ( (*pszClassThis)
165 && (pszClassThis - pszBaseClasses < cbBaseClasses)
166 )
167 {
168 if (!strcmp(pszClassThis, "WPFileSystem"))
169 *pusHiwordFileSystem = ulHiwordThis;
170 else if (!strcmp(pszClassThis, "WPAbstract"))
171 *pusHiwordAbstract = ulHiwordThis;
172
173 ulHiwordThis++;
174 pszClassThis += strlen(pszClassThis) + 1;
175 }
176
177 // now check if we found both
178 if ( (!(*pusHiwordFileSystem))
179 || (!(*pusHiwordAbstract))
180 )
181 arc = ERROR_WPH_INCOMPLETE_BASECLASS_DATA;
182
183 free(pszBaseClasses);
184 }
185 else
186 arc = ERROR_WPH_NO_BASECLASS_DATA;
187
188 return (arc);
189}
190
191/*
192 *@@ FreeChildrenTree:
193 * called from NukeNameTrees for recursion.
194 *
195 *@@added V0.9.16 (2001-10-19) [umoeller]
196 */
197
198VOID FreeChildrenTree(TREE **ppChildrenTree,
199 PLONG plCount)
200{
201 LONG cItems = *plCount;
202 TREE** papNodes = treeBuildArray(*ppChildrenTree,
203 &cItems);
204 if (papNodes)
205 {
206 ULONG ul;
207 for (ul = 0; ul < cItems; ul++)
208 {
209 PNODETREENODE pNodeThis = (PNODETREENODE)papNodes[ul];
210
211 FreeChildrenTree(&pNodeThis->ChildrenTree,
212 &pNodeThis->cChildren);
213
214 free(pNodeThis);
215 }
216
217 free(papNodes);
218 *plCount = 0;
219
220 treeInit(ppChildrenTree, plCount);
221 }
222}
223
224/*
225 *@@ NukeNameTrees:
226 * frees all cache trees.
227 *
228 *@@added V0.9.16 (2001-10-19) [umoeller]
229 */
230
231APIRET NukeNameTrees(PHANDLESBUF pHandlesBuf)
232{
233 APIRET arc = NO_ERROR;
234
235 LONG cItems = pHandlesBuf->cDrives;
236 TREE** papNodes = treeBuildArray(pHandlesBuf->DrivesTree,
237 &cItems);
238 if (papNodes)
239 {
240 ULONG ul;
241 for (ul = 0; ul < cItems; ul++)
242 {
243 PDRIVETREENODE pNodeThis = (PDRIVETREENODE)papNodes[ul];
244
245 FreeChildrenTree(&pNodeThis->ChildrenTree,
246 &pNodeThis->cChildren);
247
248 free(pNodeThis);
249 }
250
251 free(papNodes);
252
253 treeInit(&pHandlesBuf->DrivesTree,
254 &pHandlesBuf->cDrives);
255 }
256
257 return (arc);
258}
259
260/*
261 *@@ wphRebuildNodeHashTable:
262 *
263 * Returns:
264 *
265 * -- NO_ERROR
266 *
267 * -- ERROR_INVALID_PARAMETER
268 *
269 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
270 *
271 *@@added V0.9.16 (2001-10-02) [umoeller]
272 */
273
274APIRET wphRebuildNodeHashTable(HHANDLES hHandles)
275{
276 APIRET arc = NO_ERROR;
277
278 PHANDLESBUF pHandlesBuf;
279
280 if ( (!(pHandlesBuf = (PHANDLESBUF)hHandles))
281 || (!pHandlesBuf->pbData)
282 || (!pHandlesBuf->cbData)
283 )
284 arc = ERROR_INVALID_PARAMETER;
285 else
286 {
287 // start at beginning of buffer
288 PBYTE pCur = pHandlesBuf->pbData + 4;
289 PBYTE pEnd = pHandlesBuf->pbData + pHandlesBuf->cbData;
290
291 PDRIVETREENODE pLastDriveTreeNode = NULL;
292
293 memset(pHandlesBuf->NodeHashTable, 0, sizeof(pHandlesBuf->NodeHashTable));
294 NukeNameTrees(pHandlesBuf);
295
296 // now set up hash table
297 while ( (pCur < pEnd)
298 && (!arc)
299 )
300 {
301 if (!memicmp(pCur, "DRIV", 4))
302 {
303 // pCur points to a DRIVE node:
304 // these never have handles, so skip this
305 PDRIVE pDriv = (PDRIVE)pCur;
306
307 // upper the node name for string comparisons
308 strupr(pDriv->szName);
309
310 // create a drive tree node
311 // (stored so we can append to this)
312 if (!(pLastDriveTreeNode = NEW(DRIVETREENODE)))
313 arc = ERROR_NOT_ENOUGH_MEMORY;
314 else
315 {
316 pLastDriveTreeNode->Tree.ulKey = (ULONG)pDriv->szName;
317 pLastDriveTreeNode->pDriv = pDriv;
318 treeInit(&pLastDriveTreeNode->ChildrenTree,
319 &pLastDriveTreeNode->cChildren);
320 if (treeInsert(&pHandlesBuf->DrivesTree,
321 &pHandlesBuf->cDrives,
322 (TREE*)pLastDriveTreeNode,
323 treeCompareStrings))
324 arc = ERROR_WPH_DRIV_TREEINSERT_FAILED;
325 }
326
327 // next item
328 pCur += sizeof(DRIVE) + strlen(pDriv->szName);
329 }
330 else if (!memicmp(pCur, "NODE", 4))
331 {
332 // pCur points to a regular NODE: offset pointer first
333 PNODE pNode = (PNODE)pCur;
334 PNODETREENODE pNew;
335
336 // upper the node name for string comparisons
337 strupr(pNode->szName);
338
339 // create a node tree node
340 if (!(pNew = NEW(NODETREENODE)))
341 arc = ERROR_NOT_ENOUGH_MEMORY;
342 else
343 {
344 TREE **ppTree = NULL;
345 PLONG pcChildren = NULL;
346
347 pNew->Tree.ulKey = (ULONG)pNode->szName;
348 pNew->pNode = pNode;
349 treeInit(&pNew->ChildrenTree,
350 &pNew->cChildren);
351 // now check where to insert this...
352 // does it have a parent?
353 if (pNode->usParentHandle)
354 {
355 PNODETREENODE pParent;
356 if (!(pParent = pHandlesBuf->NodeHashTable[pNode->usParentHandle]))
357 // this parent handle is invalid:
358 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
359 else
360 {
361 ppTree = &pParent->ChildrenTree;
362 pcChildren = &pParent->cChildren;
363 }
364 }
365 else
366 // null parent handle: then the parent
367 // must be a DRIVE node
368 if (pLastDriveTreeNode)
369 {
370 ppTree = &pLastDriveTreeNode->ChildrenTree;
371 pcChildren = &pLastDriveTreeNode->cChildren;
372 }
373 else
374 arc = ERROR_WPH_NODE_BEFORE_DRIV;
375
376 if (!arc)
377 if (!treeInsert(ppTree,
378 pcChildren,
379 (TREE*)pNew,
380 treeCompareStrings))
381 // store PNODE in hash table
382 pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew;
383 else
384 ;
385 // @@todo if this fails, there are
386 // several handles for short name!!!
387 // arc = ERROR_WPH_NODE_TREEINSERT_FAILED;
388
389 if (arc)
390 free(pNew);
391
392 }
393
394 pCur += sizeof(NODE) + pNode->usNameSize;
395 }
396 else
397 {
398 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
399 break;
400 }
401 }
402 }
403
404 if (!arc)
405 pHandlesBuf->fCacheValid = TRUE;
406
407 return (arc);
408}
409
410/*
411 *@@ wphLoadHandles:
412 * returns a HANDLESBUF structure which will hold
413 * all the handles from OS2SYS.INI. In addition,
414 * this calls wphQueryBaseClassesHiwords and puts
415 * the hiwords for WPAbstract and WPFileSystem into
416 * the HANDLESBUF as well.
417 *
418 * Prerequisite before using any of the other wph*
419 * functions.
420 *
421 * Call wphFreeHandles to free all data allocated
422 * by this function.
423 *
424 * Returns:
425 *
426 * -- NO_ERROR
427 *
428 * -- ERROR_NOT_ENOUGH_MEMORY
429 *
430 * -- ERROR_INVALID_PARAMETER
431 *
432 * -- ERROR_WPH_NO_HANDLES_DATA: cannot read handle blocks.
433 *
434 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: cannot read handle blocks.
435 *
436 *@@added V0.9.16 (2001-10-02) [umoeller]
437 */
438
439APIRET wphLoadHandles(HINI hiniUser, // in: HINI_USER or other INI handle
440 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
441 const char *pcszActiveHandles,
442 HHANDLES *phHandles)
443{
444 APIRET arc = NO_ERROR;
445
446 if (!phHandles)
447 arc = ERROR_INVALID_PARAMETER;
448 else
449 {
450 PSZ pszKeysList;
451 if (!(arc = prfhQueryKeysForApp(hiniSystem,
452 pcszActiveHandles,
453 &pszKeysList)))
454 {
455 PHANDLESBUF pReturn = NULL;
456
457 ULONG ulHighestBlock = 0,
458 ul,
459 cbTotal;
460 PBYTE pbData;
461
462 const char *pKey2 = pszKeysList;
463 while (*pKey2)
464 {
465 if (!memicmp((PVOID)pKey2, "BLOCK", 5))
466 {
467 ULONG ulBlockThis = atoi(pKey2 + 5);
468 if (ulBlockThis > ulHighestBlock)
469 ulHighestBlock = ulBlockThis;
470 }
471
472 pKey2 += strlen(pKey2)+1; // next key
473 }
474
475 free(pszKeysList);
476
477 if (!ulHighestBlock)
478 arc = ERROR_WPH_NO_HANDLES_DATA;
479 else
480 {
481 // now go read the data
482 // (BLOCK1, BLOCK2, ..., BLOCKn)
483 cbTotal = 0;
484 pbData = NULL;
485 for (ul = 1;
486 ul <= ulHighestBlock;
487 ul++)
488 {
489 ULONG cbBlockThis;
490 CHAR szBlockThis[10];
491 sprintf(szBlockThis, "BLOCK%d", ul);
492 if (!PrfQueryProfileSize(hiniSystem,
493 (PSZ)pcszActiveHandles,
494 szBlockThis,
495 &cbBlockThis))
496 {
497 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
498 break;
499 }
500 else
501 {
502 ULONG cbTotalOld = cbTotal;
503 cbTotal += cbBlockThis;
504 if (!(pbData = (BYTE*)realloc(pbData, cbTotal)))
505 // on first call, pbData is NULL and this
506 // behaves like malloc()
507 {
508 arc = ERROR_NOT_ENOUGH_MEMORY;
509 break;
510 }
511
512 if (!PrfQueryProfileData(hiniSystem,
513 (PSZ)pcszActiveHandles,
514 szBlockThis,
515 pbData + cbTotalOld,
516 &cbBlockThis))
517 {
518 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
519 break;
520 }
521 }
522 }
523 }
524
525 if (!arc)
526 {
527 // all went OK:
528 if (pReturn = NEW(HANDLESBUF))
529 {
530 ZERO(pReturn);
531
532 treeInit(&pReturn->DrivesTree,
533 &pReturn->cDrives);
534
535 pReturn->pbData = pbData;
536 pReturn->cbData = cbTotal;
537
538 // and load the hiwords too
539 if (!(arc = wphQueryBaseClassesHiwords(hiniUser,
540 &pReturn->usHiwordAbstract,
541 &pReturn->usHiwordFileSystem)))
542 *phHandles = (HHANDLES)pReturn;
543 }
544 else
545 arc = ERROR_NOT_ENOUGH_MEMORY;
546 }
547
548 if (arc)
549 // error:
550 wphFreeHandles((HHANDLES*)&pReturn);
551 }
552 }
553
554 return (arc);
555}
556
557/*
558 *@@ wphFreeHandles:
559 * frees all data allocated by wphLoadHandles
560 * and sets *ppHandlesBuf to NULL, for safety.
561 *
562 *@@added V0.9.16 (2001-10-02) [umoeller]
563 */
564
565APIRET wphFreeHandles(HHANDLES *phHandles)
566{
567 APIRET arc = NO_ERROR;
568
569 PHANDLESBUF pHandlesBuf;
570 if ( (phHandles)
571 && (pHandlesBuf = (PHANDLESBUF)*phHandles)
572 )
573 {
574 PBYTE pbData;
575
576 NukeNameTrees(pHandlesBuf);
577
578 if (pbData = pHandlesBuf->pbData)
579 free(pbData);
580
581 free(pHandlesBuf);
582 *phHandles = NULLHANDLE;
583 }
584 else
585 arc = ERROR_INVALID_PARAMETER;
586
587 return (arc);
588}
589
590/* ******************************************************************
591 *
592 * Get HOBJECT from filename
593 *
594 ********************************************************************/
595
596/*
597 *@@ wphSearchBufferForHandle:
598 * returns the 16-bit file-system handle which corresponds
599 * to pszFilename, searching pHandlesBuffer. Note that you
600 * must OR the return value with the proper hiword to make
601 * this a valid WPS file-system handle.
602 *
603 * You must pass a handles buffer to this function which
604 * has been filled using wphReadAllBlocks above.
605 *
606 * This gets called by the one-shot function
607 * wphQueryHandleFromPath.
608 *
609 * Returns:
610 *
611 * -- NO_ERROR
612 *
613 * -- ERROR_INVALID_PARAMETER
614 *
615 * -- ERROR_FILE_NOT_FOUND
616 *
617 * -- ERROR_INVALID_NAME
618 *
619 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
620 *
621 * -- ERROR_WPH_CANNOT_FIND_HANDLE: no handle exists for the
622 * given filename.
623 *
624 *@@changed V0.9.16 (2001-10-19) [umoeller]: rewritten
625 */
626
627APIRET wphSearchBufferForHandle(HHANDLES hHandles,
628 PCSZ pcszFile, // in: fully qlf'd filename to search for
629 PUSHORT pusHandle) // out: 16-bit handle
630{
631 APIRET arc = NO_ERROR;
632
633 PHANDLESBUF pHandlesBuf;
634
635 _Pmpf((__FUNCTION__ ": entering"));
636
637 if ( (hHandles)
638 && (pHandlesBuf = (PHANDLESBUF)hHandles)
639 )
640 {
641 // rebuild cache
642 if (!pHandlesBuf->fCacheValid)
643 arc = wphRebuildNodeHashTable(hHandles);
644
645 if (!arc)
646 {
647 // We can thus work our way through the buffer by splitting the
648 // fully qualified filename that we're searching for into the
649 // different directory names and, each time, searching for the
650 // corresponding NODE. If we have found that, we go for the next.
651 // Example for C:\OS2\E.EXE:
652 // 1) first search for the "C:" NODE
653 // 2) then find the "OS2" node which has "C" as its parent NODE
654 // (we do this by comparing the parent object handles)
655 // 3) then find the "E.EXE" NODE the same way
656 // The "E.EXE" NODE then has the object handle we're looking for.
657
658 // make a copy of the filename so we can play
659 PSZ pszFilename = strdup(pcszFile),
660 pEnd = NULL;
661
662 strupr(pszFilename);
663
664 // 1) OK, find the drive.
665
666 // If this is an UNC name, the DRIVE node has the form
667 // \\SERVER\RESOURCE.
668 if ( (*pszFilename == '\\')
669 && (*(pszFilename + 1) == '\\')
670 )
671 {
672 // UNC:
673 // @@todo
674 }
675 else if (*(pszFilename + 1) == ':')
676 // extract the drive then (without \)
677 pEnd = pszFilename + 2;
678
679 if (!pEnd)
680 arc = ERROR_INVALID_NAME;
681 else
682 {
683 PDRIVETREENODE pDrive = NULL;
684 PNODETREENODE pNode;
685
686 // find the DRIVE node
687 CHAR cOld = *pEnd;
688 *pEnd = 0;
689
690 _Pmpf((" searching for drive \"%s\"", pszFilename));
691
692 if (!(pDrive = (PDRIVETREENODE)treeFind(pHandlesBuf->DrivesTree,
693 (ULONG)pszFilename, // drive name
694 treeCompareStrings)))
695 arc = ERROR_WPH_NO_MATCHING_DRIVE_BLOCK;
696 // find the root dir, which has the same name
697 else if (!(pNode = (PNODETREENODE)treeFind(pDrive->ChildrenTree,
698 (ULONG)pszFilename,
699 treeCompareStrings)))
700 arc = ERROR_WPH_NO_MATCHING_ROOT_DIR;
701 else
702 {
703 // now we got the root dir... go for next path component
704 while ( (pEnd)
705 && (*pEnd = cOld) // not null char
706 && (!arc)
707 )
708 {
709 // got another path component to search:
710 PSZ pCurrent = pEnd + 1,
711 pNext;
712
713 if (pNext = strchr(pCurrent, '\\'))
714 {
715 cOld = *pNext;
716 *pNext = 0;
717 }
718 else
719 // done:
720 cOld = 0;
721
722 _Pmpf((" searching for node \"%s\"", pCurrent));
723
724 // find the next node
725 if (!(pNode = (PNODETREENODE)treeFind(pNode->ChildrenTree,
726 (ULONG)pCurrent,
727 treeCompareStrings)))
728 arc = ERROR_WPH_CANNOT_FIND_HANDLE;
729
730 pEnd = pNext;
731 }
732
733 if (!arc && pNode)
734 // found everything:
735 *pusHandle = pNode->pNode->usHandle;
736 }
737 } // end while
738
739 free(pszFilename);
740 }
741 }
742 else
743 arc = ERROR_INVALID_PARAMETER;
744
745 _Pmpf((__FUNCTION__ ": returning %d", arc));
746
747 // not found: end of buffer reached
748 return (arc);
749}
750
751/*
752 *@@ wphQueryHandleFromPath:
753 * finds the object handle for the given fully qualified
754 * filename.
755 * This is a one-shot function, using wphQueryActiveHandles,
756 * wphReadAllBlocks, and wphSearchBufferForHandle.
757 *
758 * Returns:
759 *
760 * -- NO_ERROR: *phobj has received the object handle.
761 *
762 * -- ERROR_FILE_NOT_FOUND: file does not exist.
763 *
764 * plus the error codes of the other wph* functions called.
765 *
766 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
767 */
768
769APIRET wphQueryHandleFromPath(HINI hiniUser, // in: HINI_USER or other INI handle
770 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
771 const char *pcszName, // in: fully qlf'd filename
772 HOBJECT *phobj) // out: object handle found if NO_ERROR
773{
774 APIRET arc = NO_ERROR;
775
776 PSZ pszActiveHandles = NULL;
777 HHANDLES hHandles = NULLHANDLE;
778
779 TRY_LOUD(excpt1)
780 {
781 // not found there: check the handles then
782
783 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
784 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
785 else
786 {
787 if (arc = wphLoadHandles(hiniUser,
788 hiniSystem,
789 pszActiveHandles,
790 &hHandles))
791 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
792 else
793 {
794 USHORT usObjID;
795 CHAR szFullPath[2*CCHMAXPATH];
796 _fullpath(szFullPath, (PSZ)pcszName, sizeof(szFullPath));
797
798 // search that buffer
799 if (!(arc = wphSearchBufferForHandle(hHandles,
800 szFullPath,
801 &usObjID)))
802 // found: OR 0x30000
803 *phobj = usObjID | (((PHANDLESBUF)hHandles)->usHiwordFileSystem << 16);
804 else
805 arc = ERROR_FILE_NOT_FOUND;
806 }
807 }
808 }
809 CATCH(excpt1)
810 {
811 arc = ERROR_WPH_CRASHED;
812 } END_CATCH();
813
814 if (pszActiveHandles)
815 free(pszActiveHandles);
816 if (hHandles)
817 wphFreeHandles(&hHandles);
818
819 return (arc);
820}
821
822/* ******************************************************************
823 *
824 * Get filename from HOBJECT
825 *
826 ********************************************************************/
827
828/*
829 *@@ ComposeThis:
830 * helper for wphComposePath recursion.
831 *
832 *@@added V0.9.16 (2001-10-02) [umoeller]
833 */
834
835APIRET ComposeThis(PHANDLESBUF pHandlesBuf,
836 USHORT usHandle, // in: handle to search for
837 PXSTRING pstrFilename, // in/out: filename
838 PNODE *ppNode) // out: node found (ptr can be NULL)
839{
840 APIRET arc = NO_ERROR;
841 PNODETREENODE pTreeNode;
842 PNODE pNode;
843 if ( (pTreeNode = pHandlesBuf->NodeHashTable[usHandle])
844 && (pNode = pTreeNode->pNode)
845 )
846 {
847 // handle exists:
848 if (pNode->usParentHandle)
849 {
850 // node has parent:
851 // recurse first
852 if (arc = ComposeThis(pHandlesBuf,
853 pNode->usParentHandle,
854 pstrFilename,
855 ppNode))
856 {
857 if (arc == ERROR_INVALID_HANDLE)
858 // parent handle not found:
859 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
860 // else leave the APIRET, this might be dangerous
861 }
862 else
863 {
864 // no error:
865 xstrcatc(pstrFilename, '\\');
866 xstrcat(pstrFilename, pNode->szName, pNode->usNameSize);
867 }
868 }
869 else
870 // no parent:
871 xstrcpy(pstrFilename, pNode->szName, pNode->usNameSize);
872 }
873 else
874 arc = ERROR_INVALID_HANDLE;
875
876 if (!arc)
877 if (ppNode)
878 *ppNode = pNode;
879
880 return (arc);
881}
882
883/*
884 *@@ wphComposePath:
885 * returns the fully qualified path name for the specified
886 * file-system handle. This function is very fast because
887 * it uses a hash table for all the handles internally.
888 *
889 * Warning: This calls a helper, which recurses.
890 *
891 * This returns:
892 *
893 * -- NO_ERROR
894 *
895 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: buffer data cannot be parsed.
896 *
897 * -- ERROR_WPH_INVALID_HANDLE: usHandle cannot be found.
898 *
899 * -- ERROR_WPH_INVALID_PARENT_HANDLE: a handle was found
900 * that has a broken parent handle.
901 *
902 * -- ERROR_BUFFER_OVERFLOW: cbFilename is too small to
903 * hold the full path that was composed.
904 *
905 *@@added V0.9.16 (2001-10-02) [umoeller]
906 */
907
908APIRET wphComposePath(HHANDLES hHandles,
909 USHORT usHandle, // in: loword of handle to search for
910 PSZ pszFilename,
911 ULONG cbFilename,
912 PNODE *ppNode) // out: node found (ptr can be NULL)
913{
914 APIRET arc = NO_ERROR;
915
916 PHANDLESBUF pHandlesBuf;
917 if ( (hHandles)
918 && (pHandlesBuf = (PHANDLESBUF)hHandles)
919 )
920 {
921 TRY_LOUD(excpt1)
922 {
923 if (!pHandlesBuf->fCacheValid)
924 arc = wphRebuildNodeHashTable(hHandles);
925
926 if (!arc)
927 {
928 XSTRING str;
929 xstrInit(&str, CCHMAXPATH);
930 if (!(arc = ComposeThis(pHandlesBuf,
931 usHandle,
932 &str,
933 ppNode)))
934 if (str.ulLength > cbFilename - 1)
935 arc = ERROR_BUFFER_OVERFLOW;
936 else
937 memcpy(pszFilename,
938 str.psz,
939 str.ulLength + 1);
940 xstrClear(&str);
941 }
942 }
943 CATCH(excpt1)
944 {
945 arc = ERROR_WPH_CRASHED;
946 } END_CATCH();
947 }
948
949 return (arc);
950}
951
952/*
953 *@@ wphQueryPathFromHandle:
954 * reverse to wphQueryHandleFromPath, this gets the
955 * filename for hObject.
956 * This is a one-shot function, using wphQueryActiveHandles,
957 * wphLoadHandles, and wphComposePath.
958 * As a result, this function is _very_ expensive.
959 *
960 * Returns:
961 *
962 * -- NO_ERROR
963 *
964 * -- ERROR_INVALID_HANDLE: hObject is invalid.
965 *
966 * -- ERROR_WPH_NOT_FILESYSTEM_HANDLE: hObject's hiword is wrong.
967 *
968 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
969 */
970
971APIRET wphQueryPathFromHandle(HINI hiniUser, // in: HINI_USER or other INI handle
972 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
973 HOBJECT hObject, // in: 32-bit object handle
974 PSZ pszFilename, // out: filename, if found
975 ULONG cbFilename) // in: sizeof(*pszFilename)
976{
977 APIRET arc = NO_ERROR;
978
979 TRY_LOUD(excpt1)
980 {
981 PSZ pszActiveHandles;
982 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
983 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
984 else
985 {
986 HHANDLES hHandles;
987 if (arc = wphLoadHandles(hiniUser,
988 hiniSystem,
989 pszActiveHandles,
990 &hHandles))
991 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
992 else
993 {
994 USHORT usHiwordFileSystem = ((PHANDLESBUF)hHandles)->usHiwordFileSystem;
995
996 // is this really a file-system object?
997 if (HIUSHORT(hObject) == usHiwordFileSystem)
998 {
999 // use loword only
1000 USHORT usObjID = LOUSHORT(hObject);
1001
1002 memset(pszFilename, 0, cbFilename);
1003 arc = wphComposePath(hHandles,
1004 usObjID,
1005 pszFilename,
1006 cbFilename,
1007 NULL);
1008
1009 // _Pmpf((__FUNCTION__ ": wphFindPartName returned %d", arc));
1010 }
1011 else
1012 arc = ERROR_WPH_NOT_FILESYSTEM_HANDLE;
1013
1014 wphFreeHandles(&hHandles);
1015 }
1016
1017 free(pszActiveHandles);
1018 }
1019 }
1020 CATCH(excpt1)
1021 {
1022 arc = ERROR_WPH_CRASHED;
1023 } END_CATCH();
1024
1025 return (arc);
1026}
1027
1028
1029
Note: See TracBrowser for help on using the repository browser.