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

Last change on this file since 20 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 25.5 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 * This code is mostly written by Henk Kelder and published
15 * with his kind permission.
16 *
17 * Note: Version numbering in this file relates to XWorkplace version
18 * numbering.
19 *
20 *@@header "helpers\wphandle.h"
21 */
22
23/*
24 * This file Copyright (C) 1997-2000 Ulrich M”ller,
25 * Henk Kelder.
26 * This file is part of the "XWorkplace helpers" source package.
27 * This is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published
29 * by the Free Software Foundation, in version 2 as it comes in the
30 * "COPYING" file of the XWorkplace main distribution.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 */
36
37#define OS2EMX_PLAIN_CHAR
38 // this is needed for "os2emx.h"; if this is defined,
39 // emx will define PSZ as _signed_ char, otherwise
40 // as unsigned char
41
42#define INCL_WINSHELLDATA
43#include <os2.h>
44
45#define OPTIONS_SIZE 32767
46
47#include <stdio.h>
48#include <string.h>
49#include <stdlib.h>
50#include <io.h>
51
52#include "setup.h" // code generation and debugging options
53
54#include "helpers\wphandle.h"
55
56/****************************************************
57 * *
58 * helper functions *
59 * *
60 ****************************************************/
61
62static USHORT wphSearchBufferForHandle(PBYTE pHandlesBuffer, ULONG ulBufSize, USHORT usParent, PSZ pszFname);
63PNODE wphFindPartName(PBYTE pHandlesBuffer, ULONG ulBufSize, USHORT usID, PSZ pszFname, USHORT usMax);
64
65#define MakeDiskHandle(usObjID) (usObjID | 0x30000)
66
67#define IsObjectDisk(hObject) ((hObject & 0x30000) == 0x30000)
68
69/*
70 *@@category: Helpers\PM helpers\Workplace Shell\Handles (OS2SYS.INI)
71 */
72
73/* ******************************************************************
74 *
75 * Helper functions
76 *
77 ********************************************************************/
78
79/*
80 *@@ wphQueryProfileData:
81 * like PrfQueryProfileData, but allocates sufficient
82 * memory and returns a pointer to that buffer.
83 * pulSize must point to a ULONG which will then
84 * contain the no. of copied bytes.
85 */
86
87PBYTE wphQueryProfileData(HINI hIniSystem, // in: can be HINI_USER or HINI_SYSTEM
88 PSZ pApp, PSZ pKey, // in: load what?
89 PULONG pulSize) // out: bytes loaded
90{
91 PBYTE pData = NULL;
92 if (PrfQueryProfileSize(hIniSystem, pApp, pKey, pulSize))
93 {
94 pData = (PBYTE)malloc(*pulSize);
95 PrfQueryProfileData(hIniSystem, pApp, pKey, pData, pulSize);
96 }
97 // _Pmpf((" wphQueryProfileData(%lX, %s, %s, %d)", hIniSystem, pApp, pKey, *pulSize));
98 return (pData);
99}
100
101/*
102 *@@ wphEnumProfileKeys:
103 * allocates memory for a buffer and copies the keys
104 * for pApp into it.
105 * Returns the pointer to the buffer.
106 * pulKeysSize must point to a ULONG which will then
107 * contain the size of the returned buffer.
108 */
109
110PBYTE wphEnumProfileKeys(HINI hIniSystem, // in: can be HINI_USER or HINI_SYSTEM
111 PSZ pApp, // in: app to query
112 PULONG pulKeysSize) // out: sizeof(return buffer)
113{
114 PBYTE pszKeys = NULL;
115 if (PrfQueryProfileSize(hIniSystem, pApp, NULL, pulKeysSize))
116 {
117 pszKeys = (PBYTE)malloc(*pulKeysSize);
118 if (pszKeys)
119 PrfQueryProfileData(hIniSystem, pApp, NULL, pszKeys, pulKeysSize);
120 }
121 return (pszKeys);
122}
123
124/*
125 * wphResetBlockBuffer:
126 * Reset the block buffer, make sure the buffer is re-read.
127 */
128
129/* VOID wphResetBlockBuffer(VOID)
130{
131 if (pHandlesBuffer)
132 {
133 free(pHandlesBuffer);
134 pHandlesBuffer = NULL;
135 }
136} */
137
138/*
139 *@@ wphQueryActiveHandles:
140 * this copies the contents of PM_Workplace:ActiveHandles
141 * in OS2SYS.INI into a given buffer. There are always two
142 * buffers in OS2SYS.INI for object handles, called
143 * "PM_Workplace:HandlesX" with "X" either being "0" or "1".
144 * It seems that every time the WPS does something in the
145 * handles section, it writes the data to the inactive
146 * buffer first and then makes it the active buffer by
147 * changing the "active handles" key. You can test this
148 * by creating a shadow on your Desktop.
149 *
150 * This function copies the key only, but not the actual
151 * handles blocks (use wphReadAllBlocks for that).
152 *
153 * This gets called by the one-shot function
154 * wphQueryHandleFromPath.
155 */
156
157BOOL wphQueryActiveHandles(HINI hIniSystem, // in: can be HINI_USER or HINI_SYSTEM
158 PSZ pszHandlesAppName, // out: active handles buffer.
159 USHORT usMax) // in: sizeof(pszHandlesAppName)
160{
161 PBYTE pszHandles;
162 ULONG ulProfileSize;
163
164 pszHandles = wphQueryProfileData(hIniSystem,
165 ACTIVEHANDLES, HANDLESAPP,
166 &ulProfileSize);
167 if (!pszHandles)
168 {
169 strncpy(pszHandlesAppName, HANDLES, usMax-1);
170 return TRUE;
171 }
172 // fNewFormat = TRUE;
173 strncpy(pszHandlesAppName, pszHandles, usMax-1);
174 free(pszHandles);
175 return TRUE;
176}
177
178/*
179 *@@ wphReadAllBlocks:
180 * this reads all the BLOCK's in the active handles
181 * section in OS2SYS.INI into one common buffer, for
182 * which sufficient memory is allocated.
183 *
184 * Each of these blocks is a maximum of 64 KB, hell
185 * knows why, maybe the INIs can't handle more. This
186 * func combines all the BLOCK's into one buffer anyways,
187 * which can then be searched.
188 *
189 * Use wphQueryActiveHandles to pass the active handles
190 * section to this function.
191 *
192 * This gets called by the one-shot function
193 * wphQueryHandleFromPath.
194 */
195
196BOOL wphReadAllBlocks(HINI hiniSystem, // in: can be HINI_USER or HINI_SYSTEM
197 PSZ pszActiveHandles, // in: active handles section
198 PBYTE* ppBlock, // in/out: pointer to buffer, which
199 // will point to the allocated
200 // memory afterwards
201 PULONG pulSize) // out: size of the allocated buffer
202{
203 PBYTE pbAllBlocks,
204 pszBlockName,
205 p;
206 ULONG ulBlockSize;
207 ULONG ulTotalSize;
208 BYTE rgfBlock[100];
209 BYTE szAppName[10];
210 USHORT usBlockNo;
211
212 pbAllBlocks = wphEnumProfileKeys(hiniSystem, pszActiveHandles, &ulBlockSize);
213 if (!pbAllBlocks)
214 return FALSE;
215
216 // query size of all individual blocks and calculate total
217 memset(rgfBlock, 0, sizeof rgfBlock);
218 ulTotalSize = 0L;
219 pszBlockName = pbAllBlocks;
220 while (*pszBlockName)
221 {
222 if (!memicmp(pszBlockName, "BLOCK", 5))
223 {
224 usBlockNo = atoi(pszBlockName + 5);
225 if (usBlockNo < 100)
226 {
227 rgfBlock[usBlockNo] = TRUE;
228
229 if (!PrfQueryProfileSize(hiniSystem,
230 pszActiveHandles,
231 pszBlockName,
232 &ulBlockSize))
233 {
234 free(pbAllBlocks);
235 return FALSE;
236 }
237 ulTotalSize += ulBlockSize;
238 }
239 }
240 pszBlockName += strlen(pszBlockName) + 1;
241 }
242
243 // *pulSize now contains the total size of all blocks
244 *ppBlock = (PBYTE)malloc(ulTotalSize);
245 if (!(*ppBlock))
246 {
247 /* MessageBox("wphReadAllBlocks", "Not enough memory for profile data!"); */
248 free(pbAllBlocks);
249 return FALSE;
250 }
251
252 // now get all blocks into the memory we allocated
253 p = *ppBlock;
254 (*pulSize) = 0;
255 for (usBlockNo = 1; usBlockNo < 100; usBlockNo++)
256 {
257 if (!rgfBlock[usBlockNo])
258 break;
259
260 sprintf(szAppName, "BLOCK%u", (UINT)usBlockNo);
261 ulBlockSize = ulTotalSize;
262 if (!PrfQueryProfileData(hiniSystem,
263 pszActiveHandles,
264 szAppName,
265 p,
266 &ulBlockSize))
267 {
268 free(pbAllBlocks);
269 free(*ppBlock);
270 return FALSE;
271 }
272 p += ulBlockSize;
273 (*pulSize) += ulBlockSize;
274 ulTotalSize -= ulBlockSize;
275 }
276
277 free(pbAllBlocks);
278 return TRUE;
279}
280
281/* ******************************************************************
282 *
283 * Get HOBJECT from filename
284 *
285 ********************************************************************/
286
287/*
288 *@@ wphSearchBufferForHandle:
289 * returns the four-digit object handle which corresponds
290 * to pszFname, searching pHandlesBuffer. Note that you
291 * must OR the return value with 0x30000 to make this
292 * a valid WPS file-system handle.
293 *
294 * You must pass a handles buffer to this function which
295 * has been filled using wphReadAllBlocks above.
296 *
297 * This gets called by the one-shot function
298 * wphQueryHandleFromPath.
299 */
300
301USHORT wphSearchBufferForHandle(PBYTE pHandlesBuffer, // in: handles buffer (all BLOCK's)
302 ULONG ulBufSize, // in: sizeof(pHandlesBuffer)
303 USHORT usParent, // in: parent NODE ID;
304 // must be 0 initially
305 PSZ pszFname) // in: fully qlf'd filename to search for
306{
307 PDRIV pDriv;
308 PNODE pNode;
309 PBYTE pCur; // current
310 PBYTE p,
311 pEnd; // *end of buffer
312 USHORT usPartSize;
313
314 // _Pmpf(("Entering wphSearchBufferForHandle for %s", pszFname));
315
316 // The composed BLOCKs in the handles buffer make up a tree of
317 // DRIVE and NODE structures (see wphandle.h). Each NODE stands
318 // for either a directory or a file. (We don't care about the
319 // DRIVE structures because the root directory gets a NODE also.)
320 // Each NODE contains the non-qualified file name, an object ID,
321 // and the object ID of its parent NODE.
322 // We can thus work our way through the buffer by splitting the
323 // fully qualified filename that we're searching for into the
324 // different directory names and, each time, searching for the
325 // corresponding NODE. If we have found that, we go for the next.
326 // Example for C:\OS2\E.EXE:
327 // 1) first search for the "C:" NODE
328 // 2) then find the "OS2" node which has "C" as its parent NODE
329 // (we do this by comparing the parent object handles)
330 // 3) then find the "E.EXE" NODE the same way
331 // The "E.EXE" NODE then has the object handle we're looking for.
332
333 // So first find the length of the first filename part (which
334 // should be 2 for the drive letter, "C:")
335 p = strchr(pszFname, '\\');
336 if (p)
337 // backslash found:
338 usPartSize = p - pszFname; // extract first part
339 else
340 usPartSize = strlen(pszFname);
341
342 // now set the pointer for the end of the BLOCKs buffer
343 pEnd = pHandlesBuffer + ulBufSize;
344
345 // pCur is our variable pointer where we're at now; there
346 // is some offset of 4 bytes at the beginning (duh)
347 pCur = pHandlesBuffer + 4;
348
349 // _Pmpf((" Searching for: %s, usPartSize: %d", pszFname, usPartSize));
350
351 // go!
352 while (pCur < pEnd)
353 {
354 // the first four chars tell us whether it's
355 // a DRIVE or a NODE structure
356 if (!memicmp(pCur, "DRIV", 4))
357 {
358 // pCur points to a DRIVE node:
359 // we don't care about these, because the root
360 // directory has a real NODE too, so we just
361 // skip this
362 pDriv = (PDRIV)pCur;
363 pCur += sizeof(DRIV) + strlen(pDriv->szName);
364 }
365 else if (!memicmp(pCur, "NODE", 4))
366 {
367 // pCur points to a regular NODE: offset pointer first
368 pNode = (PNODE)pCur;
369 pCur += sizeof (NODE) + pNode->usNameSize;
370
371 // does the NODE have the same parent that we
372 // are currently searching for? This is "0"
373 // for root directories (and initially for us
374 // too)
375 if (usParent == pNode->usParentHandle)
376 {
377 // yes:
378 // _Pmpf((" found matching parents (%lX): %s", usParent, pNode->szName));
379
380 // does the NODE have the same partname length?
381 if (pNode->usNameSize == usPartSize)
382 {
383 // yes:
384 // _Pmpf((" found matching partnames sizes: %d", pNode->usNameSize));
385
386 // do the partnames match too?
387 if (memicmp(pszFname, pNode->szName, usPartSize) == 0)
388 {
389 // OK!! proper NODE found!
390 // _Pmpf((" FOUND %s!!", pNode->szName));
391
392 // now check if this was the last NODE
393 // we were looking for
394 if (strlen(pszFname) == usPartSize)
395 // yes: return ID
396 return (pNode->usHandle);
397
398 // else: update our status;
399 // get next partname
400 pszFname += usPartSize + 1;
401 // calc next partname length
402 p = strchr(pszFname, '\\');
403 if (p)
404 usPartSize = p - pszFname;
405 else
406 usPartSize = strlen(pszFname);
407
408 // get next parent to search for
409 // (which is the current handle)
410 usParent = pNode->usHandle;
411 }
412 }
413 }
414 }
415 else
416 // neither DRIVE nor NODE: error
417 return (0);
418
419 } // end while
420
421 // not found: end of buffer reached
422 return (0);
423}
424
425/*
426 *@@ wphQueryHandleFromPath:
427 * find the object handle for pszName; this
428 * can either be an object ID ("<WP_DESKTOP>")
429 * or a fully qualified filename.
430 * This is a one-shot function, using wphQueryActiveHandles,
431 * wphReadAllBlocks, and wphSearchBufferForHandle.
432 *
433 * Returns:
434 * -- -1: file does not exist
435 * -- -2: error querying handles buffer
436 * -- 0: object handle not found; might not exist
437 * -- other: found object handle
438 *
439 * NOTE: This function uses C runtime library
440 * string comparison functions. These only work
441 * properly if you have set the locale for the
442 * C runtime properly. This is, for example, a
443 * problem with file names containing German umlauts,
444 * which are not found properly.
445 * You should put some
446 + setlocale(LC_ALL, "");
447 * statement somewhere, which reacts to the LANG
448 * variable which OS/2 puts into CONFIG.SYS per
449 * default.
450 */
451
452HOBJECT wphQueryHandleFromPath(HINI hIniUser, // in: user ini file
453 HINI hIniSystem, // in: system ini file
454 PSZ pszName) // in: fully qlf'd filename
455{
456 PBYTE pHandlesBuffer = NULL;
457 ULONG cbHandlesBuffer = 0,
458 cbLocation = 0;
459 USHORT usObjID;
460 PVOID pvData;
461 HOBJECT hObject = 0L;
462 BYTE szFullPath[300];
463 CHAR szActiveHandles[100];
464
465 // _Pmpf(("wphQueryHandleFromPath: %s", pszName));
466
467 // try to get the objectID via PM_Workplace:Location, since
468 // pszName might also be a "<WP_DESKTOP>" like thingy
469 pvData = wphQueryProfileData(hIniUser,
470 LOCATION, // "PM_Workplace:Location" (<WP_DESKTOP> etc.)
471 pszName,
472 &cbLocation);
473 if (pvData)
474 {
475 // found there:
476 if (cbLocation >= sizeof(HOBJECT))
477 hObject = *(PULONG)pvData;
478 free(pvData);
479 // _Pmpf((" object ID found, hObject: %lX", hObject));
480 }
481 if (hObject)
482 return (hObject);
483
484 // not found there: is pszName an existing pathname?
485 if (access(pszName, 0)) // check existence
486 {
487 // == -1: file does not exist
488 // _Pmpf((" path not found, returning -1"));
489 return (-1);
490 }
491
492 // else: make full path for pszName
493 _fullpath(szFullPath, pszName, sizeof(szFullPath));
494
495 // check if the HandlesBlock is valid
496 wphQueryActiveHandles(hIniSystem, szActiveHandles, sizeof(szActiveHandles));
497 // _Pmpf((" szActiveHandles: %s", szActiveHandles));
498
499 // now load all the BLOCKs into a common buffer
500 if (!wphReadAllBlocks(hIniSystem,
501 szActiveHandles,
502 &pHandlesBuffer, &cbHandlesBuffer))
503 // error:
504 return (-2);
505
506 // and search that buffer
507 usObjID = wphSearchBufferForHandle(pHandlesBuffer,
508 cbHandlesBuffer,
509 0, // usParent
510 szFullPath);
511
512 if (usObjID)
513 // found: OR 0x30000
514 hObject = MakeDiskHandle(usObjID);
515
516 free(pHandlesBuffer);
517
518 return (hObject);
519}
520
521/* ******************************************************************
522 *
523 * Get filename from HOBJECT
524 *
525 ********************************************************************/
526
527/*
528 *@@ wphFindPartName:
529 * this searches pHandlesBuffer for usHandle and, if found,
530 * appends the object partname to pszFname.
531 * This function recurses, if neccessary.
532 *
533 * This gets called by the one-shot function
534 * wphQueryPathFromHandle.
535 */
536
537PNODE wphFindPartName(PBYTE pHandlesBuffer, // in: handles buffer
538 ULONG ulBufSize, // in: buffer size
539 USHORT usHandle, // in: handle to search for
540 PSZ pszFname, // out: object partname
541 USHORT usMax) // in: sizeof(pszFname)
542{
543 PDRIV pDriv;
544 PNODE pNode;
545 PBYTE p, pEnd;
546 USHORT usSize;
547
548 pEnd = pHandlesBuffer + ulBufSize;
549 p = pHandlesBuffer + 4;
550 while (p < pEnd)
551 {
552 if (!memicmp(p, "DRIV", 4))
553 {
554 pDriv = (PDRIV)p;
555 p += sizeof(DRIV) + strlen(pDriv->szName);
556 }
557 else if (!memicmp(p, "NODE", 4))
558 {
559 pNode = (PNODE)p;
560 p += sizeof (NODE) + pNode->usNameSize;
561 if (pNode->usHandle == usHandle)
562 {
563 usSize = usMax - strlen(pszFname);
564 if (usSize > pNode->usNameSize)
565 usSize = pNode->usNameSize;
566 if (pNode->usParentHandle)
567 {
568 if (!wphFindPartName(pHandlesBuffer, ulBufSize,
569 pNode->usParentHandle,
570 pszFname,
571 usMax))
572 return (NULL);
573 strcat(pszFname, "\\");
574 strncat(pszFname, pNode->szName, usSize);
575 return pNode;
576 }
577 else
578 {
579 strncpy(pszFname, pNode->szName, usSize);
580 return pNode;
581 }
582 }
583 }
584 else
585 return (NULL);
586 }
587 return (NULL);
588}
589
590/*
591 *@@ wphQueryPathFromHandle:
592 * reverse to wphQueryHandleFromPath, this gets the
593 * filename for hObject.
594 * This is a one-shot function, using wphQueryActiveHandles,
595 * wphReadAllBlocks, and wphFindPartName.
596 *
597 *@@changed V0.9.4 (2000-08-03) [umoeller]: now returning BOOL
598 */
599
600BOOL wphQueryPathFromHandle(HINI hIniSystem, // in: HINI_SYSTEM or other INI handle
601 HOBJECT hObject, // in: five-digit object handle
602 PSZ pszFname, // out: filename, if found
603 USHORT usMax) // in: sizeof(*pszFname)
604{
605 BOOL brc = FALSE;
606
607 if (IsObjectDisk(hObject))
608 {
609 // use lower byte only
610 USHORT usObjID = LOUSHORT(hObject);
611
612 PBYTE pHandlesBuffer = NULL;
613 ULONG cbHandlesBuffer = 0;
614
615 CHAR szActiveHandles[100];
616 // PNODE pReturnNode = 0;
617
618 wphQueryActiveHandles(hIniSystem, szActiveHandles, sizeof(szActiveHandles));
619
620 if (wphReadAllBlocks(hIniSystem,
621 szActiveHandles,
622 &pHandlesBuffer,
623 &cbHandlesBuffer))
624 {
625 memset(pszFname, 0, usMax);
626 if (wphFindPartName(pHandlesBuffer,
627 cbHandlesBuffer,
628 usObjID,
629 pszFname,
630 usMax))
631 brc = TRUE;
632
633 free(pHandlesBuffer);
634 }
635 }
636
637 return (brc);
638}
639
640/* ******************************************************************
641 *
642 * Manipulation functions
643 *
644 ********************************************************************/
645
646/*
647 *@@ WriteAllBlocks:
648 * writes all blocks back to OS2SYS.INI.
649 *
650 *@@added V0.9.5 (2000-08-20) [umoeller]
651 */
652
653BOOL WriteAllBlocks(HINI hini, PSZ pszHandles, PBYTE pBuffer, ULONG ulSize)
654{
655 PSZ p,
656 pEnd;
657 BYTE szBlockName[10];
658 INT iCurBlock;
659 ULONG ulCurSize;
660 PBYTE pStart;
661 PDRIV pDriv;
662 PNODE pNode;
663
664 pStart = pBuffer;
665 ulCurSize = 4;
666 p = pBuffer + 4;
667 pEnd = pBuffer + ulSize;
668 iCurBlock = 1;
669 while (p < pEnd)
670 {
671 // ULONG cbWrite = 0;
672 while (p < pEnd)
673 {
674 ULONG ulPartSize = 0;
675 if (!memicmp(p, "DRIV", 4))
676 {
677 pDriv = (PDRIV)p;
678 ulPartSize = sizeof(DRIV) + strlen(pDriv->szName);
679 }
680 else if (!memicmp(p, "NODE", 4))
681 {
682 pNode = (PNODE)p;
683 ulPartSize = sizeof (NODE) + pNode->usNameSize;
684 }
685
686 if (ulCurSize + ulPartSize > 0x0000FFFF)
687 break;
688
689 ulCurSize += ulPartSize;
690 p += ulPartSize;
691 }
692 sprintf(szBlockName, "BLOCK%d", iCurBlock++);
693
694 PrfWriteProfileData(hini,
695 pszHandles, // app
696 szBlockName, // key
697 pStart,
698 ulCurSize);
699 pStart = p;
700 ulCurSize = 0;
701 }
702
703 while (iCurBlock < 20)
704 {
705 ULONG ulBlockSize;
706
707 sprintf(szBlockName, "BLOCK%d", iCurBlock++);
708
709 if (PrfQueryProfileSize(hini,
710 pszHandles,
711 szBlockName,
712 &ulBlockSize)
713 && ulBlockSize > 0)
714 // delete block:
715 PrfWriteProfileData(hini,
716 pszHandles,
717 szBlockName,
718 NULL, 0); // delete
719 // WriteProfileData(pszHandles, szBlockName, hini, NULL, 0);
720 }
721
722 return TRUE;
723}
724
725/*
726 *@@ DeleteNode:
727 * deletes a NODE in the specified buffer.
728 *
729 *@@added V0.9.5 (2000-08-20) [umoeller]
730 */
731
732ULONG DeleteNode(PBYTE pBuffer, PNODE pNode, ULONG ulSize)
733{
734 ULONG ulDelSize = sizeof (NODE) + pNode->usNameSize;
735 USHORT usID = pNode->usHandle; // pNode->usID;
736 ULONG ulMoveSize;
737
738 if (memcmp(pNode->chName, "NODE", 4))
739 return ulSize;
740
741 ulMoveSize = (pBuffer + ulSize) - ((PBYTE)pNode + ulDelSize);
742 ulSize -= ulDelSize;
743
744 memmove(pNode, (PBYTE)pNode + ulDelSize, ulMoveSize);
745
746 while ( (PBYTE)pNode < pBuffer + ulSize
747 && !memcmp(pNode->chName, "NODE", 4)
748 && pNode->usParentHandle == usID)
749 ulSize = DeleteNode(pBuffer, pNode, ulSize);
750
751 return ulSize;
752 }
753
754/*
755 *@@ DeleteDrive:
756 * delete all information about a drive.
757 * in the specified buffer.
758 *
759 *@@added V0.9.5 (2000-08-20) [umoeller]
760 */
761
762ULONG DeleteDrive(PBYTE pBuffer, PDRIV pDriv, ULONG ulSize)
763{
764 ULONG ulDelSize;
765 ULONG ulMoveSize;
766
767 if (memcmp(pDriv->chName, "DRIV", 4))
768 return ulSize;
769
770 ulDelSize = sizeof (DRIV) + strlen(pDriv->szName);
771 ulMoveSize = (pBuffer + ulSize) - ((PBYTE)pDriv + ulDelSize);
772 ulSize -= ulDelSize;
773
774 memmove(pDriv, (PBYTE)pDriv + ulDelSize, ulMoveSize);
775 return ulSize;
776}
777
778
779
Note: See TracBrowser for help on using the repository browser.