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

Last change on this file since 368 was 368, checked in by pr, 17 years ago

Add missing header file.

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