source: branches/branch-1-0/src/helpers/wphandle.c@ 302

Last change on this file since 302 was 302, checked in by pr, 20 years ago

Fix warnings

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 36.0 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-2005 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
198STATIC VOID 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
231STATIC APIRET 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 * builds all the complex cache trees in the
263 * given handles buffer.
264 *
265 * If (fQuitOnErrors == TRUE), we'll fail as
266 * soon as an invalid handle is found. Otherwise
267 * we will try to continue if the error is not fatal.
268 *
269 * Returns:
270 *
271 * -- NO_ERROR
272 *
273 * -- ERROR_INVALID_PARAMETER
274 *
275 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
276 *
277 * -- ERROR_WPH_DRIV_TREEINSERT_FAILED: duplicate DRIV node
278 * (non-fatal)
279 *
280 *@@added V0.9.16 (2001-10-02) [umoeller]
281 *@@changted V0.9.17 (2002-02-05) [umoeller]: added fQuitOnErrors
282 */
283
284APIRET wphRebuildNodeHashTable(HHANDLES hHandles,
285 BOOL fQuitOnErrors)
286{
287 APIRET arc = NO_ERROR;
288
289 PHANDLESBUF pHandlesBuf;
290
291 if ( (!(pHandlesBuf = (PHANDLESBUF)hHandles))
292 || (!pHandlesBuf->pbData)
293 || (!pHandlesBuf->cbData)
294 )
295 arc = ERROR_INVALID_PARAMETER;
296 else
297 {
298 // start at beginning of buffer
299 PBYTE pCur = pHandlesBuf->pbData + 4;
300 PBYTE pEnd = pHandlesBuf->pbData + pHandlesBuf->cbData;
301
302 PDRIVETREENODE pLastDriveTreeNode = NULL;
303
304 memset(pHandlesBuf->NodeHashTable, 0, sizeof(pHandlesBuf->NodeHashTable));
305 NukeNameTrees(pHandlesBuf);
306
307 // now set up hash table
308 while ( (pCur < pEnd)
309 && (!arc)
310 )
311 {
312 if (!memicmp(pCur, "DRIV", 4))
313 {
314 // pCur points to a DRIVE node:
315 // these never have handles, so skip this
316 PDRIVE pDriv = (PDRIVE)pCur;
317
318 // upper the node name for string comparisons
319 strupr(pDriv->szName);
320
321 // create a drive tree node
322 // (stored so we can append to this)
323 if (!(pLastDriveTreeNode = NEW(DRIVETREENODE)))
324 arc = ERROR_NOT_ENOUGH_MEMORY;
325 else
326 {
327 pLastDriveTreeNode->Tree.ulKey = (ULONG)pDriv->szName;
328 pLastDriveTreeNode->pDriv = pDriv;
329 treeInit(&pLastDriveTreeNode->ChildrenTree,
330 &pLastDriveTreeNode->cChildren);
331 if (treeInsert(&pHandlesBuf->DrivesTree,
332 &pHandlesBuf->cDrives,
333 (TREE*)pLastDriveTreeNode,
334 treeCompareStrings))
335 if (fQuitOnErrors)
336 arc = ERROR_WPH_DRIV_TREEINSERT_FAILED;
337 }
338
339 // next item
340 pCur += sizeof(DRIVE) + strlen(pDriv->szName);
341 }
342 else if (!memicmp(pCur, "NODE", 4))
343 {
344 // pCur points to a regular NODE: offset pointer first
345 PNODE pNode = (PNODE)pCur;
346 PNODETREENODE pNew;
347
348 // upper the node name for string comparisons
349 strupr(pNode->szName);
350
351 // create a node tree node
352 if (!(pNew = NEW(NODETREENODE)))
353 arc = ERROR_NOT_ENOUGH_MEMORY;
354 else
355 {
356 TREE **ppTree = NULL;
357 PLONG pcChildren = NULL;
358
359 pNew->Tree.ulKey = (ULONG)pNode->szName;
360 pNew->pNode = pNode;
361 treeInit(&pNew->ChildrenTree,
362 &pNew->cChildren);
363 // now check where to insert this...
364 // does it have a parent?
365 if (pNode->usParentHandle)
366 {
367 PNODETREENODE pParent;
368 if (!(pParent = pHandlesBuf->NodeHashTable[pNode->usParentHandle]))
369 {
370 // this parent handle is invalid:
371 if (fQuitOnErrors)
372 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
373 }
374 else
375 {
376 ppTree = &pParent->ChildrenTree;
377 pcChildren = &pParent->cChildren;
378 }
379 }
380 else
381 // null parent handle: then the parent
382 // must be a DRIVE node
383 if (pLastDriveTreeNode)
384 {
385 ppTree = &pLastDriveTreeNode->ChildrenTree;
386 pcChildren = &pLastDriveTreeNode->cChildren;
387 }
388 else
389 if (fQuitOnErrors)
390 arc = ERROR_WPH_NODE_BEFORE_DRIV;
391
392 if (ppTree && pcChildren)
393 if (!treeInsert(ppTree,
394 pcChildren,
395 (TREE*)pNew,
396 treeCompareStrings))
397 {
398 // store PNODE in hash table
399 pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew;
400 // do not free
401 pNew = NULL;
402 }
403 else
404 ;
405 // @@todo if this fails, there are
406 // several handles for short name!!!
407 // arc = ERROR_WPH_NODE_TREEINSERT_FAILED;
408
409 if (pNew)
410 free(pNew);
411
412 }
413
414 pCur += sizeof(NODE) + pNode->usNameSize;
415 }
416 else
417 {
418 arc = ERROR_WPH_CORRUPT_HANDLES_DATA;
419 break;
420 }
421 }
422 }
423
424 if (!arc)
425 pHandlesBuf->fCacheValid = TRUE;
426
427 return arc;
428}
429
430/*
431 *@@ wphLoadHandles:
432 * returns a HANDLESBUF structure which will hold
433 * all the handles from OS2SYS.INI. In addition,
434 * this calls wphQueryBaseClassesHiwords and puts
435 * the hiwords for WPAbstract and WPFileSystem into
436 * the HANDLESBUF as well.
437 *
438 * Prerequisite before using any of the other wph*
439 * functions.
440 *
441 * Call wphFreeHandles to free all data allocated
442 * by this function.
443 *
444 * Returns:
445 *
446 * -- NO_ERROR
447 *
448 * -- ERROR_NOT_ENOUGH_MEMORY
449 *
450 * -- ERROR_INVALID_PARAMETER
451 *
452 * -- ERROR_WPH_NO_HANDLES_DATA: cannot read handle blocks.
453 *
454 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: cannot read handle blocks.
455 *
456 *@@added V0.9.16 (2001-10-02) [umoeller]
457 */
458
459APIRET wphLoadHandles(HINI hiniUser, // in: HINI_USER or other INI handle
460 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
461 const char *pcszActiveHandles,
462 HHANDLES *phHandles)
463{
464 APIRET arc = NO_ERROR;
465
466 if (!phHandles)
467 arc = ERROR_INVALID_PARAMETER;
468 else
469 {
470 PSZ pszKeysList;
471 if (!(arc = prfhQueryKeysForApp(hiniSystem,
472 pcszActiveHandles,
473 &pszKeysList)))
474 {
475 PHANDLESBUF pReturn = NULL;
476
477 ULONG ulHighestBlock = 0,
478 ul,
479 cbTotal;
480 PBYTE pbData;
481
482 const char *pKey2 = pszKeysList;
483 while (*pKey2)
484 {
485 if (!memicmp((PVOID)pKey2, "BLOCK", 5))
486 {
487 ULONG ulBlockThis = atoi(pKey2 + 5);
488 if (ulBlockThis > ulHighestBlock)
489 ulHighestBlock = ulBlockThis;
490 }
491
492 pKey2 += strlen(pKey2)+1; // next key
493 }
494
495 free(pszKeysList);
496
497 if (!ulHighestBlock)
498 arc = ERROR_WPH_NO_HANDLES_DATA;
499 else
500 {
501 // now go read the data
502 // (BLOCK1, BLOCK2, ..., BLOCKn)
503 cbTotal = 0;
504 pbData = NULL;
505 for (ul = 1;
506 ul <= ulHighestBlock;
507 ul++)
508 {
509 ULONG cbBlockThis;
510 CHAR szBlockThis[10];
511 sprintf(szBlockThis, "BLOCK%d", ul);
512 if (!PrfQueryProfileSize(hiniSystem,
513 (PSZ)pcszActiveHandles,
514 szBlockThis,
515 &cbBlockThis))
516 {
517 arc = ERROR_WPH_PRFQUERYPROFILESIZE_BLOCK;
518 break;
519 }
520 else
521 {
522 ULONG cbTotalOld = cbTotal;
523 cbTotal += cbBlockThis;
524 if (!(pbData = (BYTE*)realloc(pbData, cbTotal)))
525 // on first call, pbData is NULL and this
526 // behaves like malloc()
527 {
528 arc = ERROR_NOT_ENOUGH_MEMORY;
529 break;
530 }
531
532 if (!PrfQueryProfileData(hiniSystem,
533 (PSZ)pcszActiveHandles,
534 szBlockThis,
535 pbData + cbTotalOld,
536 &cbBlockThis))
537 {
538 arc = ERROR_WPH_PRFQUERYPROFILEDATA_BLOCK;
539 break;
540 }
541 }
542 }
543 }
544
545 if (!arc)
546 {
547 // all went OK:
548 if (pReturn = NEW(HANDLESBUF))
549 {
550 ZERO(pReturn);
551
552 treeInit(&pReturn->DrivesTree,
553 &pReturn->cDrives);
554
555 pReturn->pbData = pbData;
556 pReturn->cbData = cbTotal;
557
558 // and load the hiwords too
559 if (!(arc = wphQueryBaseClassesHiwords(hiniUser,
560 &pReturn->usHiwordAbstract,
561 &pReturn->usHiwordFileSystem)))
562 *phHandles = (HHANDLES)pReturn;
563 }
564 else
565 arc = ERROR_NOT_ENOUGH_MEMORY;
566 }
567
568 if (arc)
569 // error:
570 wphFreeHandles((HHANDLES*)&pReturn);
571 }
572 }
573
574 return arc;
575}
576
577/*
578 *@@ wphFreeHandles:
579 * frees all data allocated by wphLoadHandles
580 * and sets *ppHandlesBuf to NULL, for safety.
581 *
582 *@@added V0.9.16 (2001-10-02) [umoeller]
583 */
584
585APIRET wphFreeHandles(HHANDLES *phHandles)
586{
587 APIRET arc = NO_ERROR;
588
589 PHANDLESBUF pHandlesBuf;
590 if ( (phHandles)
591 && (pHandlesBuf = (PHANDLESBUF)*phHandles)
592 )
593 {
594 PBYTE pbData;
595
596 NukeNameTrees(pHandlesBuf);
597
598 if (pbData = pHandlesBuf->pbData)
599 free(pbData);
600
601 free(pHandlesBuf);
602 *phHandles = NULLHANDLE;
603 }
604 else
605 arc = ERROR_INVALID_PARAMETER;
606
607 return arc;
608}
609
610/* ******************************************************************
611 *
612 * Get HOBJECT from filename
613 *
614 ********************************************************************/
615
616/*
617 *@@ wphSearchBufferForHandle:
618 * returns the 16-bit file-system handle which corresponds
619 * to pszFilename, searching pHandlesBuffer. Note that you
620 * must OR the return value with the proper hiword to make
621 * this a valid WPS file-system handle.
622 *
623 * You must pass a handles buffer to this function which
624 * has been filled using wphReadAllBlocks above.
625 *
626 * This gets called by the one-shot function
627 * wphQueryHandleFromPath.
628 *
629 * Returns:
630 *
631 * -- NO_ERROR
632 *
633 * -- ERROR_INVALID_PARAMETER
634 *
635 * -- ERROR_FILE_NOT_FOUND
636 *
637 * -- ERROR_INVALID_NAME
638 *
639 * -- ERROR_WPH_CORRUPT_HANDLES_DATA
640 *
641 * -- ERROR_WPH_CANNOT_FIND_HANDLE: no handle exists for the
642 * given filename.
643 *
644 *@@changed V0.9.16 (2001-10-19) [umoeller]: rewritten
645 */
646
647APIRET wphSearchBufferForHandle(HHANDLES hHandles,
648 PCSZ pcszFile, // in: fully qlf'd filename to search for
649 PUSHORT pusHandle) // out: 16-bit handle
650{
651 APIRET arc = NO_ERROR;
652
653 PHANDLESBUF pHandlesBuf;
654
655 _Pmpf((__FUNCTION__ ": entering"));
656
657 if ( (hHandles)
658 && (pHandlesBuf = (PHANDLESBUF)hHandles)
659 )
660 {
661 // rebuild cache
662 if (!pHandlesBuf->fCacheValid)
663 arc = wphRebuildNodeHashTable(hHandles,
664 TRUE); // fail on errors
665
666 if (!arc)
667 {
668 // We can thus work our way through the buffer by splitting the
669 // fully qualified filename that we're searching for into the
670 // different directory names and, each time, searching for the
671 // corresponding NODE. If we have found that, we go for the next.
672 // Example for C:\OS2\E.EXE:
673 // 1) first search for the "C:" NODE
674 // 2) then find the "OS2" node which has "C" as its parent NODE
675 // (we do this by comparing the parent object handles)
676 // 3) then find the "E.EXE" NODE the same way
677 // The "E.EXE" NODE then has the object handle we're looking for.
678
679 // make a copy of the filename so we can play
680 PSZ pszFilename = strdup(pcszFile),
681 pEnd = NULL;
682
683 strupr(pszFilename);
684
685 // 1) OK, find the drive.
686
687 // If this is an UNC name, the DRIVE node has the form
688 // \\SERVER\RESOURCE.
689 if ( (*pszFilename == '\\')
690 && (*(pszFilename + 1) == '\\')
691 )
692 {
693 // UNC:
694 // @@todo
695 }
696 else if (*(pszFilename + 1) == ':')
697 // extract the drive then (without \)
698 pEnd = pszFilename + 2;
699
700 if (!pEnd)
701 arc = ERROR_INVALID_NAME;
702 else
703 {
704 PDRIVETREENODE pDrive = NULL;
705 PNODETREENODE pNode;
706
707 // find the DRIVE node
708 CHAR cOld = *pEnd;
709 *pEnd = 0;
710
711 _Pmpf((" searching for drive \"%s\"", pszFilename));
712
713 if (!(pDrive = (PDRIVETREENODE)treeFind(pHandlesBuf->DrivesTree,
714 (ULONG)pszFilename, // drive name
715 treeCompareStrings)))
716 arc = ERROR_WPH_NO_MATCHING_DRIVE_BLOCK;
717 // find the root dir, which has the same name
718 else if (!(pNode = (PNODETREENODE)treeFind(pDrive->ChildrenTree,
719 (ULONG)pszFilename,
720 treeCompareStrings)))
721 arc = ERROR_WPH_NO_MATCHING_ROOT_DIR;
722 else
723 {
724 // now we got the root dir... go for next path component
725 while ( (pEnd)
726 && (*pEnd = cOld) // not null char
727 && (!arc)
728 )
729 {
730 // got another path component to search:
731 PSZ pCurrent = pEnd + 1,
732 pNext;
733
734 if (pNext = strchr(pCurrent, '\\'))
735 {
736 cOld = *pNext;
737 *pNext = 0;
738 }
739 else
740 // done:
741 cOld = 0;
742
743 _Pmpf((" searching for node \"%s\"", pCurrent));
744
745 // find the next node
746 if (!(pNode = (PNODETREENODE)treeFind(pNode->ChildrenTree,
747 (ULONG)pCurrent,
748 treeCompareStrings)))
749 arc = ERROR_WPH_CANNOT_FIND_HANDLE;
750
751 pEnd = pNext;
752 }
753
754 if (!arc && pNode)
755 // found everything:
756 *pusHandle = pNode->pNode->usHandle;
757 }
758 } // end while
759
760 free(pszFilename);
761 }
762 }
763 else
764 arc = ERROR_INVALID_PARAMETER;
765
766 _Pmpf((__FUNCTION__ ": returning %d", arc));
767
768 // not found: end of buffer reached
769 return arc;
770}
771
772/*
773 *@@ wphQueryHandleFromPath:
774 * finds the object handle for the given fully qualified
775 * filename.
776 * This is a one-shot function, using wphQueryActiveHandles,
777 * wphReadAllBlocks, and wphSearchBufferForHandle.
778 *
779 * Returns:
780 *
781 * -- NO_ERROR: *phobj has received the object handle.
782 *
783 * -- ERROR_FILE_NOT_FOUND: file does not exist.
784 *
785 * plus the error codes of the other wph* functions called.
786 *
787 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
788 */
789
790APIRET wphQueryHandleFromPath(HINI hiniUser, // in: HINI_USER or other INI handle
791 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
792 const char *pcszName, // in: fully qlf'd filename
793 HOBJECT *phobj) // out: object handle found if NO_ERROR
794{
795 APIRET arc = NO_ERROR;
796
797 volatile PSZ pszActiveHandles = NULL; // XWP V1.0.4 (2005-10-09) [pr]
798 volatile HHANDLES hHandles = NULLHANDLE;
799
800 TRY_LOUD(excpt1)
801 {
802 // not found there: check the handles then
803
804 if (arc = wphQueryActiveHandles(hiniSystem, (PSZ *) &pszActiveHandles))
805 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
806 else
807 {
808 if (arc = wphLoadHandles(hiniUser,
809 hiniSystem,
810 pszActiveHandles,
811 (HHANDLES *) &hHandles))
812 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
813 else
814 {
815 USHORT usObjID;
816 CHAR szFullPath[2*CCHMAXPATH];
817 _fullpath(szFullPath, (PSZ)pcszName, sizeof(szFullPath));
818
819 // search that buffer
820 if (!(arc = wphSearchBufferForHandle(hHandles,
821 szFullPath,
822 &usObjID)))
823 // found: OR 0x30000
824 *phobj = usObjID | (((PHANDLESBUF)hHandles)->usHiwordFileSystem << 16);
825 else
826 arc = ERROR_FILE_NOT_FOUND;
827 }
828 }
829 }
830 CATCH(excpt1)
831 {
832 arc = ERROR_PROTECTION_VIOLATION; // V0.9.19 (2002-07-01) [umoeller]
833 } END_CATCH();
834
835 if (pszActiveHandles)
836 free(pszActiveHandles);
837 if (hHandles)
838 wphFreeHandles((HHANDLES *) &hHandles);
839
840 return arc;
841}
842
843/* ******************************************************************
844 *
845 * Get filename from HOBJECT
846 *
847 ********************************************************************/
848
849/*
850 *@@ ComposeThis:
851 * helper for wphComposePath recursion.
852 *
853 *@@added V0.9.16 (2001-10-02) [umoeller]
854 *@@changed V0.9.19 (2002-04-14) [umoeller]: fixed wrong error for parent handles
855 */
856
857STATIC APIRET ComposeThis(PHANDLESBUF pHandlesBuf,
858 USHORT usHandle, // in: handle to search for
859 PXSTRING pstrFilename, // in/out: filename
860 ULONG ulLevel, // in: recursion level (initially 0)
861 PNODE *ppNode) // out: node found (ptr can be NULL)
862{
863 APIRET arc = NO_ERROR;
864 PNODETREENODE pTreeNode;
865 PNODE pNode;
866 if ( (pTreeNode = pHandlesBuf->NodeHashTable[usHandle])
867 && (pNode = pTreeNode->pNode)
868 )
869 {
870 // handle exists:
871 if (pNode->usParentHandle)
872 {
873 // node has parent:
874 // recurse first
875 if (!(arc = ComposeThis(pHandlesBuf,
876 pNode->usParentHandle,
877 pstrFilename,
878 ulLevel + 1,
879 ppNode)))
880 {
881 // no error:
882 xstrcatc(pstrFilename, '\\');
883 xstrcat(pstrFilename, pNode->szName, pNode->usNameSize);
884 }
885 }
886 else
887 // no parent:
888 xstrcpy(pstrFilename, pNode->szName, pNode->usNameSize);
889 }
890 else
891 // handle not found:
892 if (ulLevel == 0) // V0.9.19 (2002-04-14) [umoeller]
893 arc = ERROR_INVALID_HANDLE;
894 else
895 arc = ERROR_WPH_INVALID_PARENT_HANDLE;
896
897 if (!arc)
898 if (ppNode)
899 *ppNode = pNode;
900
901 return arc;
902}
903
904/*
905 *@@ wphComposePath:
906 * returns the fully qualified path name for the specified
907 * file-system handle. This function is very fast because
908 * it uses a hash table for all the handles internally.
909 *
910 * Warning: This calls a helper, which recurses.
911 *
912 * This returns:
913 *
914 * -- NO_ERROR
915 *
916 * -- ERROR_WPH_CORRUPT_HANDLES_DATA: buffer data cannot be parsed.
917 *
918 * -- ERROR_WPH_INVALID_HANDLE: usHandle cannot be found.
919 *
920 * -- ERROR_WPH_INVALID_PARENT_HANDLE: a handle was found
921 * that has a broken parent handle.
922 *
923 * -- ERROR_BUFFER_OVERFLOW: cbFilename is too small to
924 * hold the full path that was composed.
925 *
926 *@@added V0.9.16 (2001-10-02) [umoeller]
927 */
928
929APIRET wphComposePath(HHANDLES hHandles,
930 USHORT usHandle, // in: loword of handle to search for
931 PSZ pszFilename,
932 ULONG cbFilename,
933 PNODE *ppNode) // out: node found (ptr can be NULL)
934{
935 APIRET arc = NO_ERROR;
936
937 PHANDLESBUF pHandlesBuf;
938 if ( (hHandles)
939 && (pHandlesBuf = (PHANDLESBUF)hHandles)
940 )
941 {
942 TRY_LOUD(excpt1)
943 {
944 if (!pHandlesBuf->fCacheValid)
945 arc = wphRebuildNodeHashTable(hHandles,
946 TRUE); // fail on errors
947
948 if (!arc)
949 {
950 XSTRING str;
951 xstrInit(&str, CCHMAXPATH);
952 if (!(arc = ComposeThis(pHandlesBuf,
953 usHandle,
954 &str,
955 0, // initial recursion level
956 ppNode)))
957 if (str.ulLength > cbFilename - 1)
958 arc = ERROR_BUFFER_OVERFLOW;
959 else
960 memcpy(pszFilename,
961 str.psz,
962 str.ulLength + 1);
963 xstrClear(&str);
964 }
965 }
966 CATCH(excpt1)
967 {
968 arc = ERROR_PROTECTION_VIOLATION; // V0.9.19 (2002-07-01) [umoeller]
969 } END_CATCH();
970 }
971
972 return arc;
973}
974
975/*
976 *@@ wphQueryPathFromHandle:
977 * reverse to wphQueryHandleFromPath, this gets the
978 * filename for hObject.
979 * This is a one-shot function, using wphQueryActiveHandles,
980 * wphLoadHandles, and wphComposePath.
981 * As a result, this function is _very_ expensive.
982 *
983 * Returns:
984 *
985 * -- NO_ERROR
986 *
987 * -- ERROR_INVALID_HANDLE: hObject is invalid.
988 *
989 * -- ERROR_WPH_NOT_FILESYSTEM_HANDLE: hObject's hiword is wrong.
990 *
991 *@@changed V0.9.16 (2001-10-02) [umoeller]: rewritten
992 */
993
994APIRET wphQueryPathFromHandle(HINI hiniUser, // in: HINI_USER or other INI handle
995 HINI hiniSystem, // in: HINI_SYSTEM or other INI handle
996 HOBJECT hObject, // in: 32-bit object handle
997 PSZ pszFilename, // out: filename, if found
998 ULONG cbFilename) // in: sizeof(*pszFilename)
999{
1000 APIRET arc = NO_ERROR;
1001
1002 TRY_LOUD(excpt1)
1003 {
1004 PSZ pszActiveHandles;
1005 if (arc = wphQueryActiveHandles(hiniSystem, &pszActiveHandles))
1006 _Pmpf((__FUNCTION__ ": wphQueryActiveHandles returned %d", arc));
1007 else
1008 {
1009 HHANDLES hHandles;
1010 if (arc = wphLoadHandles(hiniUser,
1011 hiniSystem,
1012 pszActiveHandles,
1013 &hHandles))
1014 _Pmpf((__FUNCTION__ ": wphLoadHandles returned %d", arc));
1015 else
1016 {
1017 USHORT usHiwordFileSystem = ((PHANDLESBUF)hHandles)->usHiwordFileSystem;
1018
1019 // is this really a file-system object?
1020 if (HIUSHORT(hObject) == usHiwordFileSystem)
1021 {
1022 // use loword only
1023 USHORT usObjID = LOUSHORT(hObject);
1024
1025 memset(pszFilename, 0, cbFilename);
1026 arc = wphComposePath(hHandles,
1027 usObjID,
1028 pszFilename,
1029 cbFilename,
1030 NULL);
1031
1032 // _Pmpf((__FUNCTION__ ": wphFindPartName returned %d", arc));
1033 }
1034 else
1035 arc = ERROR_WPH_NOT_FILESYSTEM_HANDLE;
1036
1037 wphFreeHandles(&hHandles);
1038 }
1039
1040 free(pszActiveHandles);
1041 }
1042 }
1043 CATCH(excpt1)
1044 {
1045 arc = ERROR_PROTECTION_VIOLATION; // V0.9.19 (2002-07-01) [umoeller]
1046 } END_CATCH();
1047
1048 return arc;
1049}
1050
1051/*
1052 *@@ wphDescribeError:
1053 * returns an error description for one of the handles
1054 * engine errors, or NULL if the error code is not
1055 * recognized.
1056 *
1057 *@@added V0.9.19 (2002-07-01) [umoeller]
1058 */
1059
1060PCSZ wphDescribeError(APIRET arc)
1061{
1062 switch (arc)
1063 {
1064 case ERROR_WPH_NO_BASECLASS_DATA:
1065 return "Cannot find PM_Workplace:BaseClass in OS2.INI";
1066
1067 case ERROR_WPH_NO_ACTIVEHANDLES_DATA:
1068 return "Cannot find PM_Workplace:ActiveHandles in OS2SYS.INI";
1069
1070 case ERROR_WPH_INCOMPLETE_BASECLASS_DATA:
1071 return "PM_Workplace:ActiveHandles in OS2SYS.INI is incomplete";
1072
1073 case ERROR_WPH_NO_HANDLES_DATA:
1074 return "Active handles block in OS2SYS.INI is empty";
1075
1076 case ERROR_WPH_CORRUPT_HANDLES_DATA:
1077 return "Cannot parse data in active handles block in OS2SYS.INI";
1078
1079 case ERROR_WPH_INVALID_PARENT_HANDLE:
1080 return "Handle has invalid parent handle";
1081
1082 case ERROR_WPH_CANNOT_FIND_HANDLE:
1083 return "No handle exists for the given filename";
1084
1085 case ERROR_WPH_DRIV_TREEINSERT_FAILED:
1086 return "Duplicate DRIV node (treeInsert failed)";
1087
1088 case ERROR_WPH_NODE_TREEINSERT_FAILED:
1089 return "Duplicate NODE node (treeInsert failed)";
1090
1091 case ERROR_WPH_NODE_BEFORE_DRIV:
1092 return "NODE node before DRIV node";
1093
1094 case ERROR_WPH_NO_MATCHING_DRIVE_BLOCK:
1095 return "No matching DRIV node";
1096
1097 case ERROR_WPH_NO_MATCHING_ROOT_DIR:
1098 return "No matching root directory";
1099
1100 case ERROR_WPH_NOT_FILESYSTEM_HANDLE:
1101 return "Handle is not a file-system handle";
1102
1103 case ERROR_WPH_PRFQUERYPROFILESIZE_BLOCK:
1104 return "PrfQueryProfileSize failed on reading one BLOCK in OS2SYS.INI";
1105
1106 case ERROR_WPH_PRFQUERYPROFILEDATA_BLOCK:
1107 return "PrfQueryProfileData failed on reading one BLOCK in OS2SYS.INI";
1108 }
1109
1110 return NULL;
1111}
Note: See TracBrowser for help on using the repository browser.