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

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

More updates.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 32.2 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 ; // @@todo if this fails, there are
382 // several handles for short name!!!
383 // arc = ERROR_WPH_NODE_TREEINSERT_FAILED;
384
385 // store PNODE in hash table
386 pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew;
387 }
388
389 pCur += sizeof(NODE) + pNode->usNameSize;
390 }
391 else
392 {
393 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
394 break;
395 }
396 }
397 }
398
399 if (!arc)
400 pHandlesBuf->fCacheValid = TRUE;
401
402 return (arc);
403}
404
405/*
406 *@@ wphLoadHandles:
407 * returns a HANDLESBUF structure which will hold
408 * all the handles from OS2SYS.INI. In addition,
409 * this calls wphQueryBaseClassesHiwords and puts
410 * the hiwords for WPAbstract and WPFileSystem into
411 * the HANDLESBUF as well.
412 *
413 * Prerequisite before using any of the other wph*
414 * functions.
415 *
416 * Call wphFreeHandles to free all data allocated
417 * by this function.
418 *
419 * Returns:
420 *
421 * -- NO_ERROR
422 *
423 * -- ERROR_NOT_ENOUGH_MEMORY
424 *
425 * -- ERROR_INVALID_PARAMETER
426 *
427 * -- ERROR_WPH_NO_HANDLES_DATA: cannot read handle blocks.
428 *
429 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: cannot read handle blocks.
430 *
431 *@@added V0.9.16 (2001-10-02) [umoeller]
432 */
433
434APIRET wphLoadHandles(HINI hiniUser, // in: HINI_USER or other INI handle
435 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
436 const char *pcszActiveHandles,
437 HHANDLES *phHandles)
438{
439 APIRET arc = NO_ERROR;
440
441 if (!phHandles)
442 arc = ERROR_INVALID_PARAMETER;
443 else
444 {
445 PSZ pszKeysList;
446 if (!(arc = prfhQueryKeysForApp(hiniSystem,
447 pcszActiveHandles,
448 &pszKeysList)))
449 {
450 PHANDLESBUF pReturn = NULL;
451
452 ULONG ulHighestBlock = 0,
453 ul,
454 cbTotal;
455 PBYTE pbData;
456
457 const char *pKey2 = pszKeysList;
458 while (*pKey2)
459 {
460 if (!memicmp((PVOID)pKey2, "BLOCK", 5))
461 {
462 ULONG ulBlockThis = atoi(pKey2 + 5);
463 if (ulBlockThis > ulHighestBlock)
464 ulHighestBlock = ulBlockThis;
465 }
466
467 pKey2 += strlen(pKey2)+1; // next key
468 }
469
470 free(pszKeysList);
471
472 if (!ulHighestBlock)
473 arc = ERROR_WPH_NO_HANDLES_DATA;
474 else
475 {
476 // now go read the data
477 // (BLOCK1, BLOCK2, ..., BLOCKn)
478 cbTotal = 0;
479 pbData = NULL;
480 for (ul = 1;
481 ul <= ulHighestBlock;
482 ul++)
483 {
484 ULONG cbBlockThis;
485 CHAR szBlockThis[10];
486 sprintf(szBlockThis, "BLOCK%d", ul);
487 if (!PrfQueryProfileSize(hiniSystem,
488 (PSZ)pcszActiveHandles,
489 szBlockThis,
490 &cbBlockThis))
491 {
492 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
493 break;
494 }
495 else
496 {
497 ULONG cbTotalOld = cbTotal;
498 cbTotal += cbBlockThis;
499 if (!(pbData = (BYTE*)realloc(pbData, cbTotal)))
500 // on first call, pbData is NULL and this
501 // behaves like malloc()
502 {
503 arc = ERROR_NOT_ENOUGH_MEMORY;
504 break;
505 }
506
507 if (!PrfQueryProfileData(hiniSystem,
508 (PSZ)pcszActiveHandles,
509 szBlockThis,
510 pbData + cbTotalOld,
511 &cbBlockThis))
512 {
513 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
514 break;
515 }
516 }
517 }
518 }
519
520 if (!arc)
521 {
522 // all went OK:
523 if (pReturn = NEW(HANDLESBUF))
524 {
525 ZERO(pReturn);
526
527 treeInit(&pReturn->DrivesTree,
528 &pReturn->cDrives);
529
530 pReturn->pbData = pbData;
531 pReturn->cbData = cbTotal;
532
533 // and load the hiwords too
534 if (!(arc = wphQueryBaseClassesHiwords(hiniUser,
535 &pReturn->usHiwordAbstract,
536 &pReturn->usHiwordFileSystem)))
537 *phHandles = (HHANDLES)pReturn;
538 }
539 else
540 arc = ERROR_NOT_ENOUGH_MEMORY;
541 }
542
543 if (arc)
544 // error:
545 wphFreeHandles((HHANDLES*)&pReturn);
546 }
547 }
548
549 return (arc);
550}
551
552/*
553 *@@ wphFreeHandles:
554 * frees all data allocated by wphLoadHandles
555 * and sets *ppHandlesBuf to NULL, for safety.
556 *
557 *@@added V0.9.16 (2001-10-02) [umoeller]
558 */
559
560APIRET wphFreeHandles(HHANDLES *phHandles)
561{
562 APIRET arc = NO_ERROR;
563
564 PHANDLESBUF pHandlesBuf;
565 if ( (phHandles)
566 && (pHandlesBuf = (PHANDLESBUF)*phHandles)
567 )
568 {
569 PBYTE pbData;
570
571 NukeNameTrees(pHandlesBuf);
572
573 if (pbData = pHandlesBuf->pbData)
574 free(pbData);
575
576 free(pHandlesBuf);
577 *phHandles = NULLHANDLE;
578 }
579 else
580 arc = ERROR_INVALID_PARAMETER;
581
582 return (arc);
583}
584
585/* ******************************************************************
586 *
587 * Get HOBJECT from filename
588 *
589 ********************************************************************/
590
591/*
592 *@@ wphSearchBufferForHandle:
593 * returns the 16-bit file-system handle which corresponds
594 * to pszFilename, searching pHandlesBuffer. Note that you
595 * must OR the return value with the proper hiword to make
596 * this a valid WPS file-system handle.
597 *
598 * You must pass a handles buffer to this function which
599 * has been filled using wphReadAllBlocks above.
600 *
601 * This gets called by the one-shot function
602 * wphQueryHandleFromPath.
603 *
604 * Returns:
605 *
606 * -- NO_ERROR
607 *
608 * -- ERROR_INVALID_PARAMETER
609 *
610 * -- ERROR_FILE_NOT_FOUND
611 *
612 * -- ERROR_INVALID_NAME
613 *
614 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
615 *
616 * -- ERROR_WPH_CANNOT_FIND_HANDLE: no handle exists for the
617 * given filename.
618 *
619 *@@changed V0.9.16 (2001-10-19) [umoeller]: rewritten
620 */
621
622APIRET wphSearchBufferForHandle(HHANDLES hHandles,
623 PCSZ pcszFile, // in: fully qlf'd filename to search for
624 PUSHORT pusHandle) // out: 16-bit handle
625{
626 APIRET arc = NO_ERROR;
627
628 PHANDLESBUF pHandlesBuf;
629
630 _Pmpf((__FUNCTION__ ": entering"));
631
632 if ( (hHandles)
633 && (pHandlesBuf = (PHANDLESBUF)hHandles)
634 )
635 {
636 // rebuild cache
637 if (!pHandlesBuf->fCacheValid)
638 arc = wphRebuildNodeHashTable(hHandles);
639
640 if (!arc)
641 {
642 // We can thus work our way through the buffer by splitting the
643 // fully qualified filename that we're searching for into the
644 // different directory names and, each time, searching for the
645 // corresponding NODE. If we have found that, we go for the next.
646 // Example for C:\OS2\E.EXE:
647 // 1) first search for the "C:" NODE
648 // 2) then find the "OS2" node which has "C" as its parent NODE
649 // (we do this by comparing the parent object handles)
650 // 3) then find the "E.EXE" NODE the same way
651 // The "E.EXE" NODE then has the object handle we're looking for.
652
653 // make a copy of the filename so we can play
654 PSZ pszFilename = strdup(pcszFile),
655 pEnd = NULL;
656
657 strupr(pszFilename);
658
659 // 1) OK, find the drive.
660
661 // If this is an UNC name, the DRIVE node has the form
662 // \\SERVER\RESOURCE.
663 if ( (*pszFilename == '\\')
664 && (*(pszFilename + 1) == '\\')
665 )
666 {
667 // UNC:
668 // @@todo
669 }
670 else if (*(pszFilename + 1) == ':')
671 // extract the drive then (without \)
672 pEnd = pszFilename + 2;
673
674 if (!pEnd)
675 arc = ERROR_INVALID_NAME;
676 else
677 {
678 PDRIVETREENODE pDrive = NULL;
679 PNODETREENODE pNode;
680
681 // find the DRIVE node
682 CHAR cOld = *pEnd;
683 *pEnd = 0;
684
685 _Pmpf((" searching for drive \"%s\"", pszFilename));
686
687 if (!(pDrive = (PDRIVETREENODE)treeFind(pHandlesBuf->DrivesTree,
688 (ULONG)pszFilename, // drive name
689 treeCompareStrings)))
690 arc = ERROR_WPH_NO_MATCHING_DRIVE_BLOCK;
691 // find the root dir, which has the same name
692 else if (!(pNode = (PNODETREENODE)treeFind(pDrive->ChildrenTree,
693 (ULONG)pszFilename,
694 treeCompareStrings)))
695 arc = ERROR_WPH_NO_MATCHING_ROOT_DIR;
696 else
697 {
698 // now we got the root dir... go for next path component
699 while ( (pEnd)
700 && (*pEnd = cOld) // not null char
701 && (!arc)
702 )
703 {
704 // got another path component to search:
705 PSZ pCurrent = pEnd + 1,
706 pNext;
707
708 if (pNext = strchr(pCurrent, '\\'))
709 {
710 cOld = *pNext;
711 *pNext = 0;
712 }
713 else
714 // done:
715 cOld = 0;
716
717 _Pmpf((" searching for node \"%s\"", pCurrent));
718
719 // find the next node
720 if (!(pNode = (PNODETREENODE)treeFind(pNode->ChildrenTree,
721 (ULONG)pCurrent,
722 treeCompareStrings)))
723 arc = ERROR_WPH_CANNOT_FIND_HANDLE;
724
725 pEnd = pNext;
726 }
727
728 if (!arc && pNode)
729 // found everything:
730 *pusHandle = pNode->pNode->usHandle;
731 }
732 } // end while
733
734 free(pszFilename);
735 }
736 }
737 else
738 arc = ERROR_INVALID_PARAMETER;
739
740 _Pmpf((__FUNCTION__ ": returning %d", arc));
741
742 // not found: end of buffer reached
743 return (arc);
744}
745
746/*
747 *@@ wphQueryHandleFromPath:
748 * finds the object handle for the given fully qualified
749 * filename.
750 * This is a one-shot function, using wphQueryActiveHandles,
751 * wphReadAllBlocks, and wphSearchBufferForHandle.
752 *
753 * Returns:
754 *
755 * -- NO_ERROR: *phobj has received the object handle.
756 *
757 * -- ERROR_FILE_NOT_FOUND: file does not exist.
758 *
759 * plus the error codes of the other wph* functions called.
760 *
761 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
762 */
763
764APIRET wphQueryHandleFromPath(HINI hiniUser, // in: HINI_USER or other INI handle
765 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
766 const char *pcszName, // in: fully qlf'd filename
767 HOBJECT *phobj) // out: object handle found if NO_ERROR
768{
769 APIRET arc = NO_ERROR;
770
771 PSZ pszActiveHandles = NULL;
772 HHANDLES hHandles = NULLHANDLE;
773
774 TRY_LOUD(excpt1)
775 {
776 // not found there: check the handles then
777
778 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
779 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
780 else
781 {
782 if (arc = wphLoadHandles(hiniUser,
783 hiniSystem,
784 pszActiveHandles,
785 &hHandles))
786 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
787 else
788 {
789 USHORT usObjID;
790 CHAR szFullPath[2*CCHMAXPATH];
791 _fullpath(szFullPath, (PSZ)pcszName, sizeof(szFullPath));
792
793 // search that buffer
794 if (!(arc = wphSearchBufferForHandle(hHandles,
795 szFullPath,
796 &usObjID)))
797 // found: OR 0x30000
798 *phobj = usObjID | (((PHANDLESBUF)hHandles)->usHiwordFileSystem << 16);
799 else
800 arc = ERROR_FILE_NOT_FOUND;
801 }
802 }
803 }
804 CATCH(excpt1)
805 {
806 arc = ERROR_WPH_CRASHED;
807 } END_CATCH();
808
809 if (pszActiveHandles)
810 free(pszActiveHandles);
811 if (hHandles)
812 wphFreeHandles(&hHandles);
813
814 return (arc);
815}
816
817/* ******************************************************************
818 *
819 * Get filename from HOBJECT
820 *
821 ********************************************************************/
822
823/*
824 *@@ ComposeThis:
825 * helper for wphComposePath recursion.
826 *
827 *@@added V0.9.16 (2001-10-02) [umoeller]
828 */
829
830APIRET ComposeThis(PHANDLESBUF pHandlesBuf,
831 USHORT usHandle, // in: handle to search for
832 PXSTRING pstrFilename, // in/out: filename
833 PNODE *ppNode) // out: node found (ptr can be NULL)
834{
835 APIRET arc = NO_ERROR;
836 PNODETREENODE pTreeNode;
837 PNODE pNode;
838 if ( (pTreeNode = pHandlesBuf->NodeHashTable[usHandle])
839 && (pNode = pTreeNode->pNode)
840 )
841 {
842 // handle exists:
843 if (pNode->usParentHandle)
844 {
845 // node has parent:
846 // recurse first
847 if (arc = ComposeThis(pHandlesBuf,
848 pNode->usParentHandle,
849 pstrFilename,
850 ppNode))
851 {
852 if (arc == ERROR_INVALID_HANDLE)
853 // parent handle not found:
854 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
855 // else leave the APIRET, this might be dangerous
856 }
857 else
858 {
859 // no error:
860 xstrcatc(pstrFilename, '\\');
861 xstrcat(pstrFilename, pNode->szName, pNode->usNameSize);
862 }
863 }
864 else
865 // no parent:
866 xstrcpy(pstrFilename, pNode->szName, pNode->usNameSize);
867 }
868 else
869 arc = ERROR_INVALID_HANDLE;
870
871 if (!arc)
872 if (ppNode)
873 *ppNode = pNode;
874
875 return (arc);
876}
877
878/*
879 *@@ wphComposePath:
880 * returns the fully qualified path name for the specified
881 * file-system handle. This function is very fast because
882 * it uses a hash table for all the handles internally.
883 *
884 * Warning: This calls a helper, which recurses.
885 *
886 * This returns:
887 *
888 * -- NO_ERROR
889 *
890 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: buffer data cannot be parsed.
891 *
892 * -- ERROR_WPH_INVALID_HANDLE: usHandle cannot be found.
893 *
894 * -- ERROR_WPH_INVALID_PARENT_HANDLE: a handle was found
895 * that has a broken parent handle.
896 *
897 * -- ERROR_BUFFER_OVERFLOW: cbFilename is too small to
898 * hold the full path that was composed.
899 *
900 *@@added V0.9.16 (2001-10-02) [umoeller]
901 */
902
903APIRET wphComposePath(HHANDLES hHandles,
904 USHORT usHandle, // in: loword of handle to search for
905 PSZ pszFilename,
906 ULONG cbFilename,
907 PNODE *ppNode) // out: node found (ptr can be NULL)
908{
909 APIRET arc = NO_ERROR;
910
911 PHANDLESBUF pHandlesBuf;
912 if ( (hHandles)
913 && (pHandlesBuf = (PHANDLESBUF)hHandles)
914 )
915 {
916 TRY_LOUD(excpt1)
917 {
918 if (!pHandlesBuf->fCacheValid)
919 arc = wphRebuildNodeHashTable(hHandles);
920
921 if (!arc)
922 {
923 XSTRING str;
924 xstrInit(&str, CCHMAXPATH);
925 if (!(arc = ComposeThis(pHandlesBuf,
926 usHandle,
927 &str,
928 ppNode)))
929 if (str.ulLength > cbFilename - 1)
930 arc = ERROR_BUFFER_OVERFLOW;
931 else
932 memcpy(pszFilename,
933 str.psz,
934 str.ulLength + 1);
935 }
936 }
937 CATCH(excpt1)
938 {
939 arc = ERROR_WPH_CRASHED;
940 } END_CATCH();
941 }
942
943 return (arc);
944}
945
946/*
947 *@@ wphQueryPathFromHandle:
948 * reverse to wphQueryHandleFromPath, this gets the
949 * filename for hObject.
950 * This is a one-shot function, using wphQueryActiveHandles,
951 * wphReadAllBlocks, and wphFindPartName.
952 *
953 * Returns:
954 *
955 * -- NO_ERROR
956 *
957 * -- ERROR_INVALID_HANDLE: hObject is invalid.
958 *
959 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
960 */
961
962APIRET wphQueryPathFromHandle(HINI hiniUser, // in: HINI_USER or other INI handle
963 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
964 HOBJECT hObject, // in: 32-bit object handle
965 PSZ pszFilename, // out: filename, if found
966 ULONG cbFilename) // in: sizeof(*pszFilename)
967{
968 APIRET arc = NO_ERROR;
969
970 TRY_LOUD(excpt1)
971 {
972 PSZ pszActiveHandles;
973 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
974 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
975 else
976 {
977 HHANDLES hHandles;
978 if (arc = wphLoadHandles(hiniUser,
979 hiniSystem,
980 pszActiveHandles,
981 &hHandles))
982 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
983 else
984 {
985 // is this really a file-system object?
986 if (HIUSHORT(hObject) == ((PHANDLESBUF)hHandles)->usHiwordFileSystem)
987 {
988 // use loword only
989 USHORT usObjID = LOUSHORT(hObject);
990
991 memset(pszFilename, 0, cbFilename);
992 arc = wphComposePath(hHandles,
993 usObjID,
994 pszFilename,
995 cbFilename,
996 NULL);
997
998 // _Pmpf((__FUNCTION__ ": wphFindPartName returned %d", arc));
999 }
1000
1001 wphFreeHandles(&hHandles);
1002 }
1003
1004 free(pszActiveHandles);
1005 }
1006 }
1007 CATCH(excpt1)
1008 {
1009 arc = ERROR_WPH_CRASHED;
1010 } END_CATCH();
1011
1012 return (arc);
1013}
1014
1015
1016
Note: See TracBrowser for help on using the repository browser.