source: trunk/pin/src/driverea.c@ 2

Last change on this file since 2 was 1, checked in by bart, 18 years ago

Initial checkin of PIN.EXE source code
this contains memory fixes for larger PPD files

File size: 13.3 KB
Line 
1/*DDK*************************************************************************/
2/* */
3/* COPYRIGHT Copyright (C) 1991, 2003 IBM Corporation */
4/* */
5/* The following IBM OS/2 source code is provided to you solely for */
6/* the purpose of assisting you in your development of OS/2 device */
7/* drivers. You may use this code in accordance with the IBM License */
8/* Agreement provided in the IBM Developer Connection Device Driver */
9/* Source Kit for OS/2. This Copyright statement may not be removed. */
10/* */
11/*****************************************************************************/
12// must audit code for memory allocation logic
13
14/**************************************************************************
15 *
16 * SOURCE FILE NAME = DRIVEREA.C
17 *
18 * DESCRIPTIVE NAME = Access and modify Extended Attributes
19 *
20 *
21 * VERSION = V1.0
22 *
23 * DATE
24 *
25 * DESCRIPTION Program configuration global variables.
26 * Also parses command line.
27 *
28 *
29 * FUNCTIONS
30 *
31 *
32 *
33 * NOTES
34 *
35 *
36 * STRUCTURES
37 *
38 * EXTERNAL REFERENCES
39 *
40 * EXTERNAL FUNCTIONS
41 *
42*/
43#define INCL_DOS
44#define INCL_DOSERRORS
45#include <os2.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49
50#include "ppb2drv.h"
51#include "lists.h"
52
53#define EA_ERROR_NOT_FOUND (ERROR_USER_DEFINED_BASE + 1)
54#define EA_ERROR_WRONG_TYPE (ERROR_USER_DEFINED_BASE + 2)
55
56#pragma pack(1)
57
58// Header for a single-valued ASCII EA data item
59typedef struct _EA_ASCII_header
60{
61 USHORT usAttr; // value: EAT_ASCII
62 USHORT usLen; // length of data
63 // ASCII data fits in here ...
64} EA_ASCII_HEADER, *PEA_ASCII_HEADER;
65
66#pragma pack()
67
68// EAQueryData: query EA data using supplied 'get' EA list into supplied
69// 'full' EA buffer - which need NOT be initialised first
70
71static
72APIRET EAQueryData( HFILE hf, PGEA2LIST pGEA2List,
73 ULONG cbBuf, PFEA2LIST pFEA2List )
74{
75 EAOP2 eaop2 = { NULL, NULL, 0 }; // EA 'root' data structure
76
77 eaop2.fpGEA2List = pGEA2List;
78 eaop2.fpFEA2List = pFEA2List;
79 pFEA2List->cbList = cbBuf; // Inform OS/2 how big our FEA2List is
80
81 return DosQueryFileInfo( hf, FIL_QUERYEASFROMLIST,
82 (PBYTE) &eaop2, sizeof ( eaop2 ) );
83}
84
85
86// EASetData: set EA data using supplied 'full' EA buffer
87
88static
89APIRET EASetData( HFILE hf, PFEA2LIST pFEA2List )
90{
91 EAOP2 eaop2 = { NULL, NULL, 0 }; // EA 'root' data structure
92
93 eaop2.fpFEA2List = pFEA2List;
94
95 return DosSetFileInfo( hf, FIL_QUERYEASIZE,
96 (PBYTE) &eaop2, sizeof ( eaop2 ));
97}
98
99// EAQueryString: query EA ASCII data into a supplied buffer as a NUL
100// terminated string.
101//
102// Note: the NUL terminator is NOT required in the data itself - it will be
103// added if required. (Some ASCII EAs include a NUL, some don't !)
104
105static
106APIRET EAQueryString( HFILE hf, PSZ pszEAName, PUSHORT pcbBuf, PSZ pszBuf )
107{
108 APIRET rc = ERROR_NOT_ENOUGH_MEMORY; // return code
109 PFEA2LIST pFEA2List = NULL; // pointer to returned EA data
110 PGEA2LIST pGEA2List = NULL; // pointer to list of EAs requested
111 PEA_ASCII_HEADER pEAData = NULL; // pointer to data item itself
112 size_t GEAlen = 0; // length of GEA list
113 size_t FEAlen = 0; // length of FEA list
114 PSZ pszAscii = NULL; // pointer to ASCII data itself
115
116
117 //
118 // Build an FEA2 list buffer with enough space for cbBuf data items
119 // The length is obtained by:
120 // size for FEA2LIST header and one FEA2 item
121 // + room for the EA name (the NUL is included in size of FEA2! )
122 // + EAT_ASCII header
123 // + up to cbBuf bytes of EAT_ASCII data (may or may not end with a NUL)
124 //
125 FEAlen = sizeof( FEA2LIST ) + strlen( pszEAName ) +
126 sizeof( EA_ASCII_HEADER ) + *pcbBuf;
127
128 // FEAlen MUST be rounded up to a doubleword boundary since
129 // OS/2 may use buffer space up to this boundary
130 FEAlen = ( ( FEAlen + 3 ) / 4 ) * 4;
131
132 pFEA2List = (PFEA2LIST) malloc( FEAlen );
133 if ( pFEA2List != NULL )
134 {
135 //
136 // Build a GEA2 list for the EA we require
137 // The length is obtained by:
138 // size for GEA2LIST header and one GEA2 item
139 // + room for the EA name (the NUL is included in the size of GEA2 !)
140 //
141 GEAlen = sizeof( GEA2LIST ) + strlen( pszEAName );
142 pGEA2List = (PGEA2LIST) malloc( GEAlen );
143 if ( pGEA2List != NULL )
144 {
145 pGEA2List->cbList = GEAlen;
146 pGEA2List->list[0].oNextEntryOffset = 0;
147 pGEA2List->list[0].cbName = (BYTE)strlen( pszEAName );
148 strcpy( pGEA2List->list[0].szName, pszEAName );
149
150 rc = EAQueryData( hf, pGEA2List, FEAlen, pFEA2List );
151 if ( rc == 0 )
152 {
153 if ( pFEA2List->list[0].cbValue == 0 )
154 {
155 // THere is no data for this EA, return an error
156 rc = EA_ERROR_NOT_FOUND;
157 }
158 else
159 {
160 // Verify the data type is what we're expecting
161 pEAData = (PEA_ASCII_HEADER) ( (PSZ)pFEA2List->list[0].szName
162 + pFEA2List->list[0].cbName + 1 );
163 if ( pEAData->usAttr == EAT_ASCII )
164 {
165 // skip ASCII header to point to ASCII data
166 pszAscii = (PSZ) (pEAData + 1);
167
168//actually we do not want to remove any trailing nulls
169// // If a trailing NUL is present, ignore it
170// if ( pszAscii[ pEAData->usLen - 1 ] == '\0' )
171// pEAData->usLen--;
172
173 if ( pEAData->usLen < *pcbBuf )
174 {
175 // Give the user the data as a NUL terminated string
176 memcpy( pszBuf, pEAData + 1, pEAData->usLen );
177 pszBuf[ pEAData->usLen ] = '\0';
178 *pcbBuf = pEAData->usLen;
179 }
180 else
181 {
182 // data read is too long for user's buffer
183 rc = ERROR_BUFFER_OVERFLOW;
184 }
185 }
186 else
187 {
188 // This function only processes EAT_ASCII !
189 rc = EA_ERROR_WRONG_TYPE;
190 }
191 }
192 }
193
194 free( pGEA2List );
195 }
196
197 free( pFEA2List );
198 }
199
200 return rc;
201}
202
203
204// EASetString: set EA ASCII data from a NUL terminated string
205//
206// Note1: the NUL terminator is NOT stored since the EAT_ASCII type already
207// includes a length field.
208// Note2: setting a string consisting only of the NUL character will delete
209// the EA.
210
211static
212APIRET EASetString( HFILE hf, PSZ pszEAName, PSZ pszBuf, USHORT cbBufLen )
213{
214 APIRET rc = ERROR_NOT_ENOUGH_MEMORY; // return code
215 PFEA2LIST pFEA2List = NULL;
216 PFEA2 pFEA2 = NULL;
217 PEA_ASCII_HEADER pEAData = NULL;
218 size_t len = 0;
219 size_t cbBuf = 0;
220
221
222 // Build an FEA2LIST buffer of the right size (see EAQueryString above)
223 len = sizeof( FEA2LIST ) + strlen( pszEAName );
224 cbBuf = cbBufLen;
225 if ( cbBuf != 0 )
226 len += sizeof( EA_ASCII_HEADER ) + cbBuf;
227
228 pFEA2List = (PFEA2LIST) malloc( len );
229 if ( pFEA2List != NULL )
230 {
231 pFEA2List->cbList = len;
232
233 pFEA2 = pFEA2List->list;
234 pFEA2->oNextEntryOffset = 0; // no more fields
235 pFEA2->fEA = 0; // no flags
236 pFEA2->cbName = (BYTE) strlen( pszEAName );
237 strcpy( pFEA2->szName, pszEAName );
238
239 if ( cbBuf == 0 )
240 pFEA2->cbValue = 0; // this will delete the EA!
241 else
242 {
243 pFEA2->cbValue = (USHORT)( sizeof( EA_ASCII_HEADER ) + cbBuf );
244
245 // Fill in the EA data area using an ASCII EA template
246 pEAData = (PEA_ASCII_HEADER) ( (PSZ)pFEA2List->list[0].szName
247 + pFEA2List->list[0].cbName + 1 );
248 pEAData->usAttr = EAT_ASCII;
249 pEAData->usLen = (USHORT) cbBuf;
250 memcpy( pEAData + 1, pszBuf, cbBuf );
251 }
252
253 rc = EASetData( hf, pFEA2List );
254
255 free( pFEA2List );
256 }
257
258 return rc;
259}
260
261
262// printrc: print an explanatory message for an OS/2 (or user-defined)
263// error code
264
265static
266void printrc( APIRET rc )
267{
268 CHAR pchBuf[512] = {'\0'};
269 ULONG ulMsgLen = 0;
270 APIRET ret = 0; /* return code from DosGetMessage() */
271
272 if (rc == 111 ) rc = 122;
273
274 ret = DosGetMessage( NULL, 0, pchBuf, 512, rc, "OSO001.MSG", &ulMsgLen);
275 if (ret == 0)
276 printf( "%.*s\n", ulMsgLen, pchBuf );
277 else if ( rc == EA_ERROR_NOT_FOUND )
278 printf( "EA item was not found\n" );
279 else if ( rc == EA_ERROR_WRONG_TYPE )
280 printf( "EA data is not simple ASCII\n" );
281 else
282 printf( "OS/2 error code: %u (look it up)\n", rc );
283}
284
285
286
287static PSZ pszBuf = NULL;
288static ULONG cbBufLen = 0;
289static HFILE hf = 0;
290
291// check if this driver version is good for us
292//
293// IMPORTANT:
294// versions:
295#define VERSION_DDPAK15 "V1.0.0"
296// initial support of external PPDs as build changes
297
298#define VERSION_DDPAK16 "V1.1.0"
299// changes for directory.ppb reading
300//
301
302
303int DriverEA_Init(PSZ pszFile)
304{
305 ULONG action = 0;
306 ULONG rc = 0;
307
308 FILESTATUS4 fi;
309
310 printf("reading driver extended attributes\n");
311
312 // check params
313 if(pszFile == NULL) goto EXIT_FAIL;
314 // ok, we're in
315
316 rc = DosOpen(pszFile, &hf, &action, 0, 0,
317 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
318 OPEN_FLAGS_NOINHERIT |
319 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
320 NULL // ea
321 );
322 if(rc) goto EXIT_FAIL;
323
324 DosQueryFileInfo( hf, FIL_QUERYEASIZE, &fi, sizeof(fi));
325 if(rc) goto EXIT_FAIL;
326
327 // alloc our string buffer
328 cbBufLen = fi.cbList + 8000;
329 pszBuf = malloc( cbBufLen );
330 if(pszBuf == NULL) goto EXIT_FAIL;
331
332 printf(" success\n");
333 return TRUE;
334
335EXIT_FAIL:
336 printf(" fail\n");
337 if(rc) printrc(rc);
338 if(hf) DosClose(hf);
339 if(pszBuf) free(pszBuf);
340 return FALSE;
341}
342
343int DriverEA_IsVersionSupported()
344{
345 USHORT cbBuf;
346 ULONG rc;
347
348 printf(" checking driver version: ");
349
350 cbBuf = cbBufLen;
351 rc = EAQueryString( hf, ".PPDIMPORTING", &cbBuf, pszBuf );
352 if(rc)
353 {
354 // error occured reading EA (as if EA not found)
355 printrc(rc);
356
357 goto EXIT_FAIL;
358 }
359
360 if(!strcmp(pszBuf,VERSION_DDPAK15))
361 ;
362 else
363 goto EXIT_FAIL;
364
365
366 printf("ok\n");
367 return TRUE;
368
369EXIT_FAIL:
370 printf("fail\n");
371 // version not recognized, we be failing
372 return FALSE;
373}
374
375int DriverEA_GetDeviceNames()
376{
377 USHORT cbBuf;
378 PSZ pszDeviceName;
379 ULONG rc;
380
381 cbBuf = cbBufLen;
382 rc = EAQueryString( hf, ".EXPAND", &cbBuf, pszBuf );
383 if(rc) goto EXIT_FAIL;
384
385 pszDeviceName = pszBuf;
386 while(strlen(pszDeviceName))
387 {
388 if(!DeviceList_AddName(pszDeviceName))
389 goto EXIT_FAIL;
390 pszDeviceName += strlen(pszDeviceName) + 1;
391 }
392
393 return 1;
394
395EXIT_FAIL:
396 DeviceList_Destroy();
397 return 0;
398}
399
400int DriverEA_SetDeviceNames()
401{
402 USHORT cbBuf;
403 PSZ pszDeviceName;
404 PSZ pszInBuf;
405 ULONG rc;
406
407 cbBuf = 0;
408 pszDeviceName = DeviceList_GetName(1);
409 while(pszDeviceName)
410 {
411 pszInBuf = pszBuf + cbBuf;
412 if(cbBuf+strlen(pszDeviceName)+1 > cbBufLen) break;
413 cbBuf+=strlen(pszDeviceName)+1;
414
415 strcpy (pszInBuf,pszDeviceName);
416
417 pszDeviceName = DeviceList_GetName(0);
418 }
419
420 pszBuf[cbBuf]=0; // two zeros mark end of data
421 cbBuf++;
422 rc = EASetString( hf, ".EXPAND", pszBuf, cbBuf );
423 if(rc) goto EXIT_FAIL;
424
425 return 1;
426EXIT_FAIL:
427 return 0;
428}
429
430int DriverEA_GetRequiredFiles()
431{
432 USHORT cbBuf;
433 PSZ pszFileName1;
434 PSZ pszFileName2;
435 ULONG rc;
436
437 cbBuf = cbBufLen;
438 rc = EAQueryString( hf, "REQUIREDDRIVERFILES", &cbBuf, pszBuf );
439 if(rc) goto EXIT_FAIL;
440
441 pszFileName1 = pszBuf;
442 do
443 {
444 pszFileName2 = strchr(pszFileName1,',');
445 if(pszFileName2)
446 {
447 *pszFileName2 = 0;
448 pszFileName2++;
449 }
450
451 if(!ReqfileList_AddName(pszFileName1))
452 goto EXIT_FAIL;
453 pszFileName1 = pszFileName2;
454 } while(pszFileName1);
455
456 return 1;
457
458EXIT_FAIL:
459 ReqfileList_Destroy();
460 return 0;
461}
462
463int DriverEA_SetRequiredFiles()
464{
465 USHORT cbBuf;
466 PSZ pszFileName;
467 PSZ pszInBuf;
468 ULONG rc;
469
470 cbBuf = 0;
471 pszFileName = ReqfileList_GetName(1);
472 while(pszFileName)
473 {
474 pszInBuf = pszBuf + cbBuf;
475 if(cbBuf+strlen(pszFileName) > cbBufLen) break;
476 cbBuf+=strlen(pszFileName);
477
478 strcpy (pszInBuf,pszFileName);
479
480 pszFileName = ReqfileList_GetName(0);
481 if(pszFileName)
482 strcat(pszInBuf,",");
483 cbBuf+=1;
484 }
485
486 rc = EASetString( hf, "REQUIREDDRIVERFILES", pszBuf, cbBuf );
487 //ReqfileList_Destroy();
488
489 return 1;
490EXIT_FAIL:
491 return 0;
492}
493
494int DriverEA_Done()
495{
496 free(pszBuf);
497 pszBuf = NULL;
498 cbBufLen = 0;
499
500 DosClose(hf);
501 hf = 0;
502
503 return 1;
504}
505
506
Note: See TracBrowser for help on using the repository browser.