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

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

Fix nlsUpper() for DBCS.
Make file handles code DBCS safe. Bug 1070.

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