Драйвер принтера и DEVMODE

Тема в разделе "WASM.WIN32", создана пользователем wdm, 31 дек 2008.

  1. wdm

    wdm New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2008
    Сообщения:
    3
    Здравствуйте уважаемые знатоки ассемблера и программирования под Win32.
    С наступающим Новым Годом Вас.
    А теперь вопрос:
    В printer interface DLL есть точка входа
    Код (Text):
    1. BOOL
    2.   DrvConvertDevMode(
    3.     LPTSTR  pPrinterName,
    4.     PDEVMODE  pdmIn,
    5.     PDEVMODE  pdmOut,
    6.     PLONG  pcbNeeded,
    7.     DWORD  fMode
    8.     );
    Когда fMode == CDM_DRIVER_DEFAULT
    функция должна в конечном итоге скопировать в pdmOut DEVMODE по умолчанию.

    DEVMODE определена так (начало определения )
    Код (Text):
    1. typedef struct _devicemodew {
    2.   WCHAR dmDeviceName[CCHDEVICENAME];
    3.   WORD dmSpecVersion;
    4.   WORD dmDriverVersion;
    5.   WORD dmSize;
    6. ...
    где CCHDEVICENAME == 32
    На мой "непросвещенный" взгляд в памяти это все должно располагаться
    "примерно" так: 32*2 байта dmDeviceName, 2 байта dmSpecVersion и так далее.
    Собственно так и получается. Но, при попытке установить драйвер принтера, спулер падает со страшным
    грохотом и в отладчике выпадает вот в таком месте:
    Код (Text):
    1. 77C37FCC  mov         edi,edi
    2. 77C37FCE  push        ebp  
    3. 77C37FCF  mov         ebp,esp
    4. 77C37FD1  mov         eax,dword ptr [ebp+8]
    5. 77C37FD4  mov         cx,word ptr [eax]                ; вот на это отладчик и ругаеццо. WinDbg считает что это в wcslen
    6. 77C37FD7  inc         eax  
    7. 77C37FD8  inc         eax  
    8. 77C37FD9  test        cx,cx
    ругаецца он потому что eax содержит указатель на "что попало".
    При чем тут DEVMODE?
    Если например заполнить поле dmDeviceName следующей строчкой L"Mega" то
    в заполненой структурке в памяти увидим следующее:

    0x00A7E958 4d 00 65 00 67 00 61 00 00 00 00 00 00 M.e.g.a......
    0x00A7E965 00 00 00 00 00 00 00 00 00 00 00 00 00 .............

    что собственно и ожидалось. Но ни как не ожидалось что что содержимое eax будет 0x0065004d.
    Получаецца что спулер, а вернее провайдер печати, воспринимают DEVMODE как
    Код (Text):
    1. typedef struct _devicemodew {
    2.   WCHAR* dmDeviceName;
    3.   WORD dmSpecVersion;
    4.   WORD dmDriverVersion;
    5.   WORD dmSize;
    6. ...
    Вопрос - это я в шары долблюсь(неправ) или децствительно есть "альтернативное" определение DEVMODE?
    Ос WinXp
    Заранее благодарен за любой ответ. Еще раз с праздником.
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    wdm
    Какая связь приведённого куска кода с DrvConvertDevMode и DEVMODE ?

    Видно, что это начало какой-то ф-ции, вероятно берущей первым аргументом указатель на WCHAR-строку (или указатель на структуру, с такой строкой первым полем). Т.е. вполне возможно, что первый арг. - это указатель на DEVMODE.
    Откуда такой вывод? Из приведённого кода это не следует.
     
  3. wdm

    wdm New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2008
    Сообщения:
    3
    DrvConvertDevMode возвращает спулеру заполненную DEVMODE.
    спулер (локальный провайдер печати) "что-то" с ней делает и попадает в это место.
    Приведенный кусок кода это место где собственно и происходит ошибка. WinDbg говорит что это msvcrt.dll и ф-ция wcslen. соответственно первый аргумент и есть WCHAR-строка.
    кусок кода просто скопирован из окна отладчика для иллюстрации.
    Ошибка происходит если я заполняю в DEVMODE поле dmDeviceName. И я просто обратил внимание что первые четыре байта, которые я записываю в это поле попадают в качестве адреса строки в wcslen.
    Собственно потому я такой вывод и сделал. Это следует не из приведенного кода.
    Я конечно предполагаю, что возможной причиной ошибки является некорректное заполнение мной DEVMODE, но...
    Код (Text):
    1. BOOL
    2.   DrvConvertDevMode(
    3.     LPTSTR  pPrinterName,
    4.     PDEVMODE  pdmIn,
    5.     PDEVMODE  pdmOut,
    6.     PLONG  pcbNeeded,
    7.     DWORD  fMode
    8.     ){
    9.         DbgMessageW( L"PlotUI: DrvConvertDevMode\n" );
    10.     DbgMessageW( L"PlotUI: pPrinterName == %s\n", pPrinterName );
    11.     DbgMessageW( L"PlotUI: Needed: %u\n\r", *pcbNeeded );
    12.  
    13.     bool bRes = false; 
    14.    
    15.     switch(fMode){
    16.         case CDM_CONVERT:
    17.             DbgMessageW( L"PlotUI: fMode == CDM_CONVERT\n" );
    18.             break;
    19.         case CDM_CONVERT351:
    20.             DbgMessageW( L"PlotUI: fMode == CDM_CONVERT351\n" );
    21.             break;
    22.         case CDM_DRIVER_DEFAULT:
    23.             DbgMessageW( L"PlotUI: fMode == CDM_DRIVER_DEFAULT\n" );
    24.             if( (*pcbNeeded < sizeof(DEVMODE)) || (pdmOut == NULL) ){                    
    25.                       *pcbNeeded = sizeof(DEVMODE);
    26.                        SetLastError( ERROR_INSUFFICIENT_BUFFER );  
    27.                                    DbgMessageW( L"PlotUI: ERROR_INSUFFICIENT_BUFFER. Needed: %u\n\r", sizeof(DEVMODE) );       
    28.                        bRes = false;
    29.                 }else{ 
    30.  
    31.                       *pcbNeeded= sizeof(DEVMODE); 
    32.                                     memset( pdmOut, 0, sizeof( DEVMODE ) );
    33.  
    34.                                     wcsncpy( pdmOut->dmDeviceName, L"MegaPlotter", wcslen(L"MegaPlotter") );           
    35.                          pdmOut->dmSize         = sizeof(DEVMODE);     
    36.                          pdmOut->dmSpecVersion      = DM_SPECVERSION;
    37.                          pdmOut->dmDriverVersion        = 4;
    38.                          pdmOut->dmDriverExtra      = 0;
    39.                          pdmOut->dmFields           = DM_ORIENTATION|DM_PAPERLENGTH
    40.                                       |DM_PAPERWIDTH|DM_SCALE|DM_DEFAULTSOURCE
    41.                                       |DM_PRINTQUALITY|DM_COLOR|DM_DUPLEX;
    42.  
    43.                          pdmOut->dmOrientation      = DMORIENT_LANDSCAPE;
    44.                          pdmOut->dmPaperLength      = 10000;
    45.                          pdmOut->dmPaperWidth       = 10000;
    46.                          pdmOut->dmScale            = 100;
    47.                          pdmOut->dmDefaultSource    = DMBIN_MANUAL;
    48.                          pdmOut->dmPrintQuality     = DMRES_HIGH;
    49.                          pdmOut->dmColor            = DMCOLOR_MONOCHROME;
    50.                          pdmOut->dmDuplex           = DMDUP_SIMPLEX;   
    51.                         DbgMessageW( L"PlotUI: Copy DEVMODE\n\r" );
    52.                         bRes = true;
    53.                 }      
    54.             break;
    55.         default:
    56.             DbgMessageW( L"PlotUI: fMode == DEFAULT\n" );
    57.     };
    58.     return bRes;
    59. }
    Вот на всякий случай моя DrvConvertDevMode ....
    Вроде бы все тупо до невозможности
     
  4. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    wdm
    Грох происходит после вызова DrvConvertDevMode, но до вызова всех других ф-ций драйвера?

    Вот это ошибка, кстати:
    Нужно:
     
  5. wdm

    wdm New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2008
    Сообщения:
    3
    Код (Text):
    1. Нужно:
    2.     wcsncpy( pdmOut->dmDeviceName, L"MegaPlotter", CCHDEVICENAME) );
    Я так и делал изначально. В данном случае не играет ни какой роли...я так понимаю..
    Да. Сразу после вызова DrvConvertDevMode :dntknw: