1 /* 2 * Metafile driver initialisation functions 3 * 4 * Copyright 1996 Alexandre Julliard 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <string.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "winnls.h" 27 #include "gdi_private.h" 28 #include "mfdrv/metafiledrv.h" 29 #include "wine/debug.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(metafile); 32 33 static BOOL MFDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ); 34 static BOOL MFDRV_DeleteDC( PHYSDEV dev ); 35 36 37 /********************************************************************** 38 * MFDRV_ExtEscape 39 */ 40 static INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data, 41 INT cbOutput, LPVOID out_data ) 42 { 43 METARECORD *mr; 44 DWORD len; 45 INT ret; 46 47 if (cbOutput) return 0; /* escapes that require output cannot work in metafiles */ 48 49 len = sizeof(*mr) + sizeof(WORD) + ((cbInput + 1) & ~1); 50 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 51 mr->rdSize = len / 2; 52 mr->rdFunction = META_ESCAPE; 53 mr->rdParm[0] = nEscape; 54 mr->rdParm[1] = cbInput; 55 memcpy(&(mr->rdParm[2]), in_data, cbInput); 56 ret = MFDRV_WriteRecord( dev, mr, len); 57 HeapFree(GetProcessHeap(), 0, mr); 58 return ret; 59 } 60 61 62 /****************************************************************** 63 * MFDRV_GetBoundsRect 64 */ 65 static UINT MFDRV_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags ) 66 { 67 return 0; 68 } 69 70 71 /****************************************************************** 72 * MFDRV_SetBoundsRect 73 */ 74 static UINT MFDRV_SetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags ) 75 { 76 return 0; 77 } 78 79 80 /****************************************************************** 81 * MFDRV_GetDeviceCaps 82 * 83 *A very simple implementation that returns DT_METAFILE 84 */ 85 static INT MFDRV_GetDeviceCaps(PHYSDEV dev, INT cap) 86 { 87 switch(cap) 88 { 89 case TECHNOLOGY: 90 return DT_METAFILE; 91 case TEXTCAPS: 92 return 0; 93 default: 94 TRACE(" unsupported capability %d, will return 0\n", cap ); 95 } 96 return 0; 97 } 98 99 100 static const struct gdi_dc_funcs MFDRV_Funcs = 101 { 102 NULL, /* pAbortDoc */ 103 MFDRV_AbortPath, /* pAbortPath */ 104 NULL, /* pAlphaBlend */ 105 NULL, /* pAngleArc */ 106 MFDRV_Arc, /* pArc */ 107 NULL, /* pArcTo */ 108 MFDRV_BeginPath, /* pBeginPath */ 109 NULL, /* pBlendImage */ 110 MFDRV_Chord, /* pChord */ 111 MFDRV_CloseFigure, /* pCloseFigure */ 112 MFDRV_CreateCompatibleDC, /* pCreateCompatibleDC */ 113 NULL, /* pCreateDC */ 114 MFDRV_DeleteDC, /* pDeleteDC */ 115 MFDRV_DeleteObject, /* pDeleteObject */ 116 NULL, /* pDeviceCapabilities */ 117 MFDRV_Ellipse, /* pEllipse */ 118 NULL, /* pEndDoc */ 119 NULL, /* pEndPage */ 120 MFDRV_EndPath, /* pEndPath */ 121 NULL, /* pEnumFonts */ 122 NULL, /* pEnumICMProfiles */ 123 MFDRV_ExcludeClipRect, /* pExcludeClipRect */ 124 NULL, /* pExtDeviceMode */ 125 MFDRV_ExtEscape, /* pExtEscape */ 126 MFDRV_ExtFloodFill, /* pExtFloodFill */ 127 MFDRV_ExtSelectClipRgn, /* pExtSelectClipRgn */ 128 MFDRV_ExtTextOut, /* pExtTextOut */ 129 MFDRV_FillPath, /* pFillPath */ 130 MFDRV_FillRgn, /* pFillRgn */ 131 MFDRV_FlattenPath, /* pFlattenPath */ 132 NULL, /* pFontIsLinked */ 133 MFDRV_FrameRgn, /* pFrameRgn */ 134 NULL, /* pGdiComment */ 135 MFDRV_GetBoundsRect, /* pGetBoundsRect */ 136 NULL, /* pGetCharABCWidths */ 137 NULL, /* pGetCharABCWidthsI */ 138 NULL, /* pGetCharWidth */ 139 NULL, /* pGetCharWidthInfo */ 140 MFDRV_GetDeviceCaps, /* pGetDeviceCaps */ 141 NULL, /* pGetDeviceGammaRamp */ 142 NULL, /* pGetFontData */ 143 NULL, /* pGetFontRealizationInfo */ 144 NULL, /* pGetFontUnicodeRanges */ 145 NULL, /* pGetGlyphIndices */ 146 NULL, /* pGetGlyphOutline */ 147 NULL, /* pGetICMProfile */ 148 NULL, /* pGetImage */ 149 NULL, /* pGetKerningPairs */ 150 NULL, /* pGetNearestColor */ 151 NULL, /* pGetOutlineTextMetrics */ 152 NULL, /* pGetPixel */ 153 NULL, /* pGetSystemPaletteEntries */ 154 NULL, /* pGetTextCharsetInfo */ 155 NULL, /* pGetTextExtentExPoint */ 156 NULL, /* pGetTextExtentExPointI */ 157 NULL, /* pGetTextFace */ 158 NULL, /* pGetTextMetrics */ 159 NULL, /* pGradientFill */ 160 MFDRV_IntersectClipRect, /* pIntersectClipRect */ 161 MFDRV_InvertRgn, /* pInvertRgn */ 162 MFDRV_LineTo, /* pLineTo */ 163 NULL, /* pModifyWorldTransform */ 164 MFDRV_MoveTo, /* pMoveTo */ 165 MFDRV_OffsetClipRgn, /* pOffsetClipRgn */ 166 MFDRV_OffsetViewportOrgEx, /* pOffsetViewportOrgEx */ 167 MFDRV_OffsetWindowOrgEx, /* pOffsetWindowOrgEx */ 168 MFDRV_PaintRgn, /* pPaintRgn */ 169 MFDRV_PatBlt, /* pPatBlt */ 170 MFDRV_Pie, /* pPie */ 171 MFDRV_PolyBezier, /* pPolyBezier */ 172 MFDRV_PolyBezierTo, /* pPolyBezierTo */ 173 NULL, /* pPolyDraw */ 174 MFDRV_PolyPolygon, /* pPolyPolygon */ 175 NULL, /* pPolyPolyline */ 176 MFDRV_Polygon, /* pPolygon */ 177 MFDRV_Polyline, /* pPolyline */ 178 NULL, /* pPolylineTo */ 179 NULL, /* pPutImage */ 180 NULL, /* pRealizeDefaultPalette */ 181 MFDRV_RealizePalette, /* pRealizePalette */ 182 MFDRV_Rectangle, /* pRectangle */ 183 NULL, /* pResetDC */ 184 MFDRV_RestoreDC, /* pRestoreDC */ 185 MFDRV_RoundRect, /* pRoundRect */ 186 MFDRV_SaveDC, /* pSaveDC */ 187 MFDRV_ScaleViewportExtEx, /* pScaleViewportExtEx */ 188 MFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */ 189 MFDRV_SelectBitmap, /* pSelectBitmap */ 190 MFDRV_SelectBrush, /* pSelectBrush */ 191 MFDRV_SelectClipPath, /* pSelectClipPath */ 192 MFDRV_SelectFont, /* pSelectFont */ 193 MFDRV_SelectPalette, /* pSelectPalette */ 194 MFDRV_SelectPen, /* pSelectPen */ 195 NULL, /* pSetArcDirection */ 196 MFDRV_SetBkColor, /* pSetBkColor */ 197 MFDRV_SetBkMode, /* pSetBkMode */ 198 MFDRV_SetBoundsRect, /* pSetBoundsRect */ 199 MFDRV_SetDCBrushColor, /* pSetDCBrushColor*/ 200 MFDRV_SetDCPenColor, /* pSetDCPenColor*/ 201 MFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */ 202 NULL, /* pSetDeviceClipping */ 203 NULL, /* pSetDeviceGammaRamp */ 204 NULL, /* pSetLayout */ 205 MFDRV_SetMapMode, /* pSetMapMode */ 206 MFDRV_SetMapperFlags, /* pSetMapperFlags */ 207 MFDRV_SetPixel, /* pSetPixel */ 208 MFDRV_SetPolyFillMode, /* pSetPolyFillMode */ 209 MFDRV_SetROP2, /* pSetROP2 */ 210 MFDRV_SetRelAbs, /* pSetRelAbs */ 211 MFDRV_SetStretchBltMode, /* pSetStretchBltMode */ 212 MFDRV_SetTextAlign, /* pSetTextAlign */ 213 MFDRV_SetTextCharacterExtra, /* pSetTextCharacterExtra */ 214 MFDRV_SetTextColor, /* pSetTextColor */ 215 MFDRV_SetTextJustification, /* pSetTextJustification */ 216 MFDRV_SetViewportExtEx, /* pSetViewportExtEx */ 217 MFDRV_SetViewportOrgEx, /* pSetViewportOrgEx */ 218 MFDRV_SetWindowExtEx, /* pSetWindowExtEx */ 219 MFDRV_SetWindowOrgEx, /* pSetWindowOrgEx */ 220 NULL, /* pSetWorldTransform */ 221 NULL, /* pStartDoc */ 222 NULL, /* pStartPage */ 223 MFDRV_StretchBlt, /* pStretchBlt */ 224 MFDRV_StretchDIBits, /* pStretchDIBits */ 225 MFDRV_StrokeAndFillPath, /* pStrokeAndFillPath */ 226 MFDRV_StrokePath, /* pStrokePath */ 227 NULL, /* pUnrealizePalette */ 228 MFDRV_WidenPath, /* pWidenPath */ 229 NULL, /* wine_get_wgl_driver */ 230 GDI_PRIORITY_GRAPHICS_DRV /* priority */ 231 }; 232 233 234 235 /********************************************************************** 236 * MFDRV_AllocMetaFile 237 */ 238 static DC *MFDRV_AllocMetaFile(void) 239 { 240 DC *dc; 241 METAFILEDRV_PDEVICE *physDev; 242 243 if (!(dc = alloc_dc_ptr( OBJ_METADC ))) return NULL; 244 245 physDev = HeapAlloc(GetProcessHeap(),0,sizeof(*physDev)); 246 if (!physDev) 247 { 248 free_dc_ptr( dc ); 249 return NULL; 250 } 251 if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) ))) 252 { 253 HeapFree( GetProcessHeap(), 0, physDev ); 254 free_dc_ptr( dc ); 255 return NULL; 256 } 257 258 push_dc_driver( &dc->physDev, &physDev->dev, &MFDRV_Funcs ); 259 260 physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0])); 261 physDev->handles_size = HANDLE_LIST_INC; 262 physDev->cur_handles = 0; 263 264 physDev->hFile = 0; 265 266 physDev->mh->mtHeaderSize = sizeof(METAHEADER) / sizeof(WORD); 267 physDev->mh->mtVersion = 0x0300; 268 physDev->mh->mtSize = physDev->mh->mtHeaderSize; 269 physDev->mh->mtNoObjects = 0; 270 physDev->mh->mtMaxRecord = 0; 271 physDev->mh->mtNoParameters = 0; 272 273 SetVirtualResolution( physDev->dev.hdc, 0, 0, 0, 0); 274 275 return dc; 276 } 277 278 279 /********************************************************************** 280 * MFDRV_CreateCompatibleDC 281 */ 282 static BOOL MFDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ) 283 { 284 /* not supported on metafile DCs */ 285 return FALSE; 286 } 287 288 289 /********************************************************************** 290 * MFDRV_DeleteDC 291 */ 292 static BOOL MFDRV_DeleteDC( PHYSDEV dev ) 293 { 294 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; 295 DWORD index; 296 297 HeapFree( GetProcessHeap(), 0, physDev->mh ); 298 for(index = 0; index < physDev->handles_size; index++) 299 if(physDev->handles[index]) 300 GDI_hdc_not_using_object(physDev->handles[index], dev->hdc); 301 HeapFree( GetProcessHeap(), 0, physDev->handles ); 302 HeapFree( GetProcessHeap(), 0, physDev ); 303 return TRUE; 304 } 305 306 307 /********************************************************************** 308 * CreateMetaFileW (GDI32.@) 309 * 310 * Create a new DC and associate it with a metafile. Pass a filename 311 * to create a disk-based metafile, NULL to create a memory metafile. 312 * 313 * PARAMS 314 * filename [I] Filename of disk metafile 315 * 316 * RETURNS 317 * A handle to the metafile DC if successful, NULL on failure. 318 */ 319 HDC WINAPI CreateMetaFileW( LPCWSTR filename ) 320 { 321 HDC ret; 322 DC *dc; 323 METAFILEDRV_PDEVICE *physDev; 324 HANDLE hFile; 325 DWORD bytes_written; 326 327 TRACE("%s\n", debugstr_w(filename) ); 328 329 if (!(dc = MFDRV_AllocMetaFile())) return 0; 330 physDev = (METAFILEDRV_PDEVICE *)dc->physDev; 331 332 if (filename) /* disk based metafile */ 333 { 334 physDev->mh->mtType = METAFILE_DISK; 335 if ((hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, 336 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { 337 free_dc_ptr( dc ); 338 return 0; 339 } 340 if (!WriteFile( hFile, physDev->mh, sizeof(*physDev->mh), 341 &bytes_written, NULL )) { 342 free_dc_ptr( dc ); 343 CloseHandle (hFile ); 344 return 0; 345 } 346 physDev->hFile = hFile; 347 348 /* Grow METAHEADER to include filename */ 349 physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename, TRUE); 350 } 351 else /* memory based metafile */ 352 physDev->mh->mtType = METAFILE_MEMORY; 353 354 TRACE("returning %p\n", physDev->dev.hdc); 355 ret = physDev->dev.hdc; 356 release_dc_ptr( dc ); 357 return ret; 358 } 359 360 /********************************************************************** 361 * CreateMetaFileA (GDI32.@) 362 * 363 * See CreateMetaFileW. 364 */ 365 HDC WINAPI CreateMetaFileA(LPCSTR filename) 366 { 367 LPWSTR filenameW; 368 DWORD len; 369 HDC hReturnDC; 370 371 if (!filename) return CreateMetaFileW(NULL); 372 373 len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 ); 374 filenameW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); 375 MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len ); 376 377 hReturnDC = CreateMetaFileW(filenameW); 378 379 HeapFree( GetProcessHeap(), 0, filenameW ); 380 381 return hReturnDC; 382 } 383 384 385 /********************************************************************** 386 * MFDRV_CloseMetaFile 387 */ 388 static DC *MFDRV_CloseMetaFile( HDC hdc ) 389 { 390 DC *dc; 391 METAFILEDRV_PDEVICE *physDev; 392 DWORD bytes_written; 393 394 TRACE("(%p)\n", hdc ); 395 396 if (!(dc = get_dc_ptr( hdc ))) return NULL; 397 if (GetObjectType( hdc ) != OBJ_METADC) 398 { 399 release_dc_ptr( dc ); 400 return NULL; 401 } 402 if (dc->refcount != 1) 403 { 404 FIXME( "not deleting busy DC %p refcount %u\n", hdc, dc->refcount ); 405 release_dc_ptr( dc ); 406 return NULL; 407 } 408 physDev = (METAFILEDRV_PDEVICE *)dc->physDev; 409 410 /* Construct the end of metafile record - this is documented 411 * in SDK Knowledgebase Q99334. 412 */ 413 414 if (!MFDRV_MetaParam0(dc->physDev, META_EOF)) 415 { 416 free_dc_ptr( dc ); 417 return 0; 418 } 419 420 if (physDev->mh->mtType == METAFILE_DISK) /* disk based metafile */ 421 { 422 if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) { 423 free_dc_ptr( dc ); 424 return 0; 425 } 426 427 physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */ 428 if (!WriteFile(physDev->hFile, physDev->mh, sizeof(*physDev->mh), 429 &bytes_written, NULL)) { 430 free_dc_ptr( dc ); 431 return 0; 432 } 433 CloseHandle(physDev->hFile); 434 physDev->mh->mtType = METAFILE_DISK; 435 } 436 437 return dc; 438 } 439 440 /****************************************************************** 441 * CloseMetaFile (GDI32.@) 442 * 443 * Stop recording graphics operations in metafile associated with 444 * hdc and retrieve metafile. 445 * 446 * PARAMS 447 * hdc [I] Metafile DC to close 448 * 449 * RETURNS 450 * Handle of newly created metafile on success, NULL on failure. 451 */ 452 HMETAFILE WINAPI CloseMetaFile(HDC hdc) 453 { 454 HMETAFILE hmf; 455 METAFILEDRV_PDEVICE *physDev; 456 DC *dc = MFDRV_CloseMetaFile(hdc); 457 if (!dc) return 0; 458 physDev = (METAFILEDRV_PDEVICE *)dc->physDev; 459 460 /* Now allocate a global handle for the metafile */ 461 462 hmf = MF_Create_HMETAFILE( physDev->mh ); 463 464 physDev->mh = NULL; /* So it won't be deleted */ 465 free_dc_ptr( dc ); 466 return hmf; 467 } 468 469 470 /****************************************************************** 471 * MFDRV_WriteRecord 472 * 473 * Warning: this function can change the pointer to the metafile header. 474 */ 475 BOOL MFDRV_WriteRecord( PHYSDEV dev, METARECORD *mr, DWORD rlen) 476 { 477 DWORD len, size; 478 METAHEADER *mh; 479 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; 480 481 switch(physDev->mh->mtType) 482 { 483 case METAFILE_MEMORY: 484 len = physDev->mh->mtSize * 2 + rlen; 485 /* reallocate memory if needed */ 486 size = HeapSize( GetProcessHeap(), 0, physDev->mh ); 487 if (len > size) 488 { 489 /*expand size*/ 490 size += size / 2 + rlen; 491 mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, size); 492 if (!mh) return FALSE; 493 physDev->mh = mh; 494 TRACE("Reallocated metafile: new size is %d\n",size); 495 } 496 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen); 497 break; 498 case METAFILE_DISK: 499 TRACE("Writing record to disk\n"); 500 if (!WriteFile(physDev->hFile, mr, rlen, NULL, NULL)) 501 return FALSE; 502 break; 503 default: 504 ERR("Unknown metafile type %d\n", physDev->mh->mtType ); 505 return FALSE; 506 } 507 508 physDev->mh->mtSize += rlen / 2; 509 physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2); 510 return TRUE; 511 } 512 513 514 /****************************************************************** 515 * MFDRV_MetaParam0 516 */ 517 518 BOOL MFDRV_MetaParam0(PHYSDEV dev, short func) 519 { 520 char buffer[8]; 521 METARECORD *mr = (METARECORD *)&buffer; 522 523 mr->rdSize = 3; 524 mr->rdFunction = func; 525 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 526 } 527 528 529 /****************************************************************** 530 * MFDRV_MetaParam1 531 */ 532 BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1) 533 { 534 char buffer[8]; 535 METARECORD *mr = (METARECORD *)&buffer; 536 WORD *params = mr->rdParm; 537 538 mr->rdSize = 4; 539 mr->rdFunction = func; 540 params[0] = param1; 541 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 542 } 543 544 545 /****************************************************************** 546 * MFDRV_MetaParam2 547 */ 548 BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2) 549 { 550 char buffer[10]; 551 METARECORD *mr = (METARECORD *)&buffer; 552 WORD *params = mr->rdParm; 553 554 mr->rdSize = 5; 555 mr->rdFunction = func; 556 params[0] = param2; 557 params[1] = param1; 558 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 559 } 560 561 562 /****************************************************************** 563 * MFDRV_MetaParam4 564 */ 565 566 BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2, 567 short param3, short param4) 568 { 569 char buffer[14]; 570 METARECORD *mr = (METARECORD *)&buffer; 571 WORD *params = mr->rdParm; 572 573 mr->rdSize = 7; 574 mr->rdFunction = func; 575 params[0] = param4; 576 params[1] = param3; 577 params[2] = param2; 578 params[3] = param1; 579 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 580 } 581 582 583 /****************************************************************** 584 * MFDRV_MetaParam6 585 */ 586 587 BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2, 588 short param3, short param4, short param5, short param6) 589 { 590 char buffer[18]; 591 METARECORD *mr = (METARECORD *)&buffer; 592 WORD *params = mr->rdParm; 593 594 mr->rdSize = 9; 595 mr->rdFunction = func; 596 params[0] = param6; 597 params[1] = param5; 598 params[2] = param4; 599 params[3] = param3; 600 params[4] = param2; 601 params[5] = param1; 602 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 603 } 604 605 606 /****************************************************************** 607 * MFDRV_MetaParam8 608 */ 609 BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2, 610 short param3, short param4, short param5, 611 short param6, short param7, short param8) 612 { 613 char buffer[22]; 614 METARECORD *mr = (METARECORD *)&buffer; 615 WORD *params = mr->rdParm; 616 617 mr->rdSize = 11; 618 mr->rdFunction = func; 619 params[0] = param8; 620 params[1] = param7; 621 params[2] = param6; 622 params[3] = param5; 623 params[4] = param4; 624 params[5] = param3; 625 params[6] = param2; 626 params[7] = param1; 627 return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); 628 } 629