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

Last change on this file since 49 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.