Re: Драйвер - як його написати та і що це?

На одному з іноземних форумів мені дали таку наступну відповідь

You have extern "C" { in some files, but not in all ones. Thus the name mangling mismatch.

Я набрав у гуглі що це, і ось припустимо результат

https://stackoverflow.com/questions/104 … f-extern-c


Звісно що я не знавець английської, і тільки де-ні де впізнаю знайомі слова.

Ось ця фраза стала ключовою- я одразу усе зрозумів. Майже се інше до купи не склалося.

extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client 'C' linker will then link to using the 'C' name.

С++ спотворює імена функції щоб мати змогу мати декилька перевантажених функцій з різними аргументами, так до речі я зрозумів.

Я навмання поставив всі функції єкстерном-Си.  Я не дуже соображаю що ж я зробив!

Але якщо це просто знак компілятору не змінювати назви функцій, то тоді в чому може бути проблема? Просте завдання! і де ж коріннямурага помилки?

Я точно не зрозумів досконально що Єкстерн-Си зробить!
Гаразд, я не додумав, я піду на дві-три години, я подумаю, чи прочитаю, або перепитаю ще.

22 Востаннє редагувалося Дмитро-Чебурашка (03.03.2016 15:06:15)

Re: Драйвер - як його написати та і що це?

Прихований текст

//////////////////////////////////////////////

#include "Driver.h"

// Предварительные объявления функций:
NTSTATUS DeviceControlRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp );
VOID     UnloadRoutine(IN PDRIVER_OBJECT DriverObject);
NTSTATUS ReadWrite_IRPhandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp );
NTSTATUS Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);

extern "C"
NTSTATUS Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{
#if DBG
DbgPrint("-Primer- In Close handler."); 
#endif
return CompleteIrp(Irp,STATUS_SUCCESS,0);
}

// Хотя и нехорошо делать глобальные переменные в драйвере...
KSPIN_LOCK MySpinLock;
#pragma code_seg("INIT") // начало секции INIT


extern "C"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, //об'єкт драйвера, містить покажчики на всі необхідні операційній системі функції, які ми повинні будемо ініціювати.
                      IN PUNICODE_STRING RegistryPath  ) //ім'я розділу в реєстрі, де зберігається інформація про даний драйвер.
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_OBJECT  fdo;
    UNICODE_STRING  devName;

    #if DBG
    DbgPrint("=Example= In DriverEntry.");
    DbgPrint("=Example= RegistryPath = %ws.", RegistryPath->Buffer);
    #endif
    
    
    // DriverObject->DriverExtension->AddDevice= OurAddDeviceRoutine;
    DriverObject->DriverUnload = UnloadRoutine;
    DriverObject->MajorFunction[IRP_MJ_CREATE]= Create_File_IRPprocessing;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = Close_HandleIRPprocessing;
    DriverObject->MajorFunction[IRP_MJ_READ]  = ReadWrite_IRPhandler;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = ReadWrite_IRPhandler;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= DeviceControlRoutine;
    //========================================================
    
    RtlInitUnicodeString( &devName, L"\\Device\\EXAMPLE" );

    // Создаем наш Functional Device Object (FDO) и получаем
    // указатель на созданный FDO в нашей переменной fdo.    
    
    status = IoCreateDevice(DriverObject,     
                            sizeof(EXAMPLE_DEVICE_EXTENSION),
                            &devName, 
                            FILE_DEVICE_UNKNOWN, 
                            0,
                            FALSE, 
                            &fdo);
    if(!NT_SUCCESS(status)) return status;

    
    PEXAMPLE_DEVICE_EXTENSION dx = (PEXAMPLE_DEVICE_EXTENSION)fdo->DeviceExtension;
    dx->fdo = fdo;  
    
    #if DBG
    DbgPrint("=Example= FDO %X, DevExt=%X.",fdo,dx);
    #endif

    //=======================================
    
    UNICODE_STRING symLinkName;   
    #define    SYM_LINK_NAME    L"\\DosDevices\\Example"
    RtlInitUnicodeString(      
                          &symLinkName, 
                          SYM_LINK_NAME ); 
    dx->ustrSymLinkName = symLinkName;
    
    
    
    status = IoCreateSymbolicLink( &symLinkName, &devName );
    if (!NT_SUCCESS(status))
    { // при неудаче √ удалить Device Object и вернуть управление
        IoDeleteDevice( fdo );
        return status;
        } 
        KeInitializeSpinLock(&MySpinLock);
      
        #if DBG
        DbgPrint("=Example= DriverEntry successfully completed.");
        #endif
        return status;
}
#pragma code_seg() // end INIT section





extern "C"
NTSTATUS CompleteIrp( PIRP Irp, NTSTATUS status, ULONG info)
{
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;//Параметр info, если он не равен нулю, чаще всего содержит число байт, переданных клиенту (полученных от клиента) драйвера
    IoCompleteRequest(Irp,IO_NO_INCREMENT);
    return status;
}


extern "C"
NTSTATUS ReadWrite_IRPhandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp )
{
    ULONG BytesTxd = 0;
    NTSTATUS status = STATUS_SUCCESS; //Завершение с кодом status
    // Задаем печать отладочных сообщений √ если сборка отладочная
    #if DBG
    DbgPrint("-Example- in ReadWrite_IRPhandler.");
    #endif
    return CompleteIrp(Irp,status,BytesTxd);
}



extern "C"
NTSTATUS Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
    // Задаем печать отладочных сообщений - если сборка отладочная
    #if DBG
    DbgPrint("-Example- Create File is %ws",
        &(IrpStack->FileObject->FileName.Buffer));
    #endif
return CompleteIrp(Irp,STATUS_SUCCESS,0); // Успешное завершение
}



extern "C"
NTSTATUS DeviceControlRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG BytesTxd =0; 
    PIO_STACK_LOCATION IrpStack=IoGetCurrentIrpStackLocation(Irp);

    PEXAMPLE_DEVICE_EXTENSION dx =
                 (PEXAMPLE_DEVICE_EXTENSION)fdo->DeviceExtension;
    //-------------------------------
    
    ULONG ControlCode =
    IrpStack->Parameters.DeviceIoControl.IoControlCode;
    ULONG method = ControlCode & 0x03;
    KIRQL irql,
    currentIrql = KeGetCurrentIrql();

    #if DBG
    DbgPrint("-Example- In DeviceControlRoutine (fdo= %X)\n",fdo);
    DbgPrint("-Example- DeviceIoControl: IOCTL %x.", ControlCode );
    if(currentIrql==PASSIVE_LEVEL)
        DbgPrint("-Example- PASSIVE_LEVEL (val=%d)",currentIrql);
    #endif
     
    KeAcquireSpinLock(&MySpinLock,&irql);

     
    switch( ControlCode) {

    #ifndef SMALL_VERSION
    case IOCTL_PRINT_DEBUG_MESS:
    {      
        #if DBG
        DbgPrint("-Example- IOCTL_PRINT_DEBUG_MESS.");
        #endif
        break;
    }
    case IOCTL_CHANGE_IRQL:
    {
        #if DBG
         
         
        DbgPrint("-Example- IOCTL_CHANGE_IRQL.");
        KIRQL dl = DISPATCH_LEVEL,  
        oldIrql,
        newIrql=25;  
         
        KeRaiseIrql(newIrql,&oldIrql);
        newIrql=KeGetCurrentIrql();  

        DbgPrint("-Example- DISPATCH_LEVEL value =%d",dl);
        DbgPrint("-Example- IRQLs are old=%d new=%d",
                        oldIrql,newIrql);
        KeLowerIrql(oldIrql);  
        #endif
        break;
    }
    #endif  


    case IOCTL_MAKE_SYSTEM_CRASH:
    {
        int errDetected=0;
        char x = (char)0xFF;

        #if    DBG   
        DbgPrint("-Example- IOCTL_MAKE_SYSTEM_CRASH.");
        #endif
         
        __try {
        x = *(char*)0x0L;  
             
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {    
             
             
            errDetected=1;
        };
        #if DBG
        DbgPrint("-Example- Value of x is %X.",x);
        if(errDetected)
            DbgPrint("-Example- Except detected in Example driver.");
        #endif
        break;
    }

    #ifndef SMALL_VERSION
    case IOCTL_TOUCH_PORT_378H:
    {    
        unsigned short ECRegister = 0x378+0x402;
        #if DBG
        DbgPrint("-Example- IOCTL_TOUCH_PORT_378H.");
        #endif
         
         
         
        _asm  {
            mov dx,ECRegister ;
            xor al,al    ;
            out dx,al    ;    Установить EPP mode 000
            mov al,095h  ;    Биты 7:5 = 100
            out dx,al    ;    Установить EPP mode 100
        }
           
        //  
        break;
    }

    case IOCTL_SEND_BYTE_TO_USER:
    {    
         
        ULONG InputLength =  
            IrpStack->Parameters.DeviceIoControl.InputBufferLength;
         
        ULONG OutputLength =
        IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
        #if DBG
        DbgPrint("-Example- Buffer outlength %d",OutputLength);
        #endif

        if( OutputLength<1 )
        { 
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        UCHAR *buff;  
        if(method==METHOD_BUFFERED)
        {
            buff = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
            #if DBG
            DbgPrint("-Example- Method : BUFFERED.");
            #endif
        }
        else
            if (method==METHOD_NEITHER)
            {
                buff=(unsigned char*)Irp->UserBuffer;
                #if DBG
                DbgPrint("-Example- Method : NEITHER.");
                #endif
            }
            else
            {
                #if DBG
                DbgPrint("-Example- Method : unsupported.");
                #endif
                status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }
        #if DBG
        DbgPrint("-Example- Buffer address is %08X",buff);
        #endif
        *buff=33;      
        BytesTxd = 1;  
        break;
    }
    #endif  
     
    default: status = STATUS_INVALID_DEVICE_REQUEST;
    }
     
    KeReleaseSpinLock(&MySpinLock,irql);

    #if DBG
    DbgPrint("-Example- DeviceIoControl: %d bytes written.", (int)BytesTxd);
    #endif

return CompleteIrp(Irp,status,BytesTxd);  
}



 

#pragma code_seg("PAGE")
 
extern "C"
VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject)
{
    PDEVICE_OBJECT    pNextDevObj;
    int i;

     
    #if DBG
    DbgPrint("-Example- In Unload Routine.");
    #endif
    //==========================================================
     
    pNextDevObj = pDriverObject->DeviceObject;

    for(i=0; pNextDevObj!=NULL; i++)
    {
        PEXAMPLE_DEVICE_EXTENSION dx =
                (PEXAMPLE_DEVICE_EXTENSION)pNextDevObj->DeviceExtension;
         
        UNICODE_STRING *pLinkName = & (dx->ustrSymLinkName);
          
        pNextDevObj = pNextDevObj->NextDevice;

        #if DBG
        DbgPrint("-Example- Deleted device (%d) : pointer to FDO = %X.",
                            i,dx->fdo);
        DbgPrint("-Example- Deleted symlink = %ws.", pLinkName->Buffer);
        #endif

        IoDeleteSymbolicLink(pLinkName);
        IoDeleteDevice( dx->fdo);
    }
}
#pragma code_seg()  

Re: Драйвер - як його написати та і що це?

1)   Якщо я пишукод для драйвєра, чі краще мені всі його функциїкомпілювати як extern C?  Або ж краще як С++?
Або буває що так, а бувае й що ні?
  Що саме для драйвєрів найкраще частіше?

2) Якщо я попередоб'явлею функцію а потім пишу її код повністю, тоді  extern C трєба писати перед - попередоб'явою, або й перед-попередоб'явою і перед описом функції відразу, або ж як?


3) Якщо я включаю інший файл інклюдом, і перед цим інклюдом напишу extern C так тоди що, це буде ніби як я попєред кожною функцією його написав, або це ніби-то щось інше,  вважається?

24 Востаннє редагувалося Дмитро-Чебурашка (03.03.2016 22:41:34)

Re: Драйвер - як його написати та і що це?

Знайшов в яндексі приклад.

Частина коду

#ifndef _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ //
эти строки запрещают повторный проход по тексту заголовочных 
#define _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ // (*.h) файлов, что особенно актуально для больших проектов 
// и повышает скорость компиляции
#ifdef __cplusplus
extern «C»
{
#endif

#include «ntddk.h» // если заменить эту строку на #include «wdm.h», то компиляция драйвера
(с использованием Build из DDK)
// пройдёт успешно, но WDM он всё равно не станет 

#ifdef __cplusplus
}
#endif



З логіки видно явно, що якщо мовляв компілюємо як С ++ то тоді і тільки тоді включаємо «ntddk.h». Офігєть !!!
А інакше не включаємо? Я Щось нє зрозумів?

Іншу логіку тут важко й припустити, так і виходить, а __cplusplus відповідно повинен тоді визначатися будь-яким
плюсовим компілятором.

Далі! Цілий ряд функцій оголошується просто і прямо; Раптом !!!


extern «C»
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 

{
NTSTATUS status = STATUS_SUCCESS;

А ні!!! Брешу!

Ряд функцій оголошується вище, потім, нижче цієї ось функції DriverEntry, вони вже описуються.
І описуються без усіляких extern "C".
А записані вони для використання - усєредині функції DriverEntry як різні частини масиву MajorFunction!
Може воно так й трєба ?! А знайшов я цей код на сайти хакер-ру по запитанню ntddk.h що це?, і це і є той мій код
з книзі Солдатова!Принаймєні сходжий до офігеть!  АА!! Хабрахабр!! Та я все плутаю. Я одразу копыюю до нотепаду і почінаю як завгодно переробляти, переставляти , шукати та таке..

25 Востаннє редагувалося Дмитро-Чебурашка (03.03.2016 22:29:42)

Re: Драйвер - як його написати та і що це?

Не всі функциї, ось NTSTATUS CompleteIrp(PIRP Irp, NTSTATUS status, ULONG info)
оголошений без усяких extern «C»! Без та й усе.

Взагалі стає питання, якщо дана ось така контструкція, то що???  Функциї всередині функциї що оголошена як extern «C»
також будуть extern «C» бо ж не інакше?

extern "C" { extern "C" { .. } } ??


А якщо у мене є файл  Deyaky.cpp який включає в себе файл   Fil.hh який сопряжоний з файлом Fil.cpp який  включає до себе файл
Fil2.h, який включає в себе ще інший заголовок файлу Fil2.cpp,то як це все працює?

26 Востаннє редагувалося Дмитро-Чебурашка (04.03.2016 00:04:06)

Re: Драйвер - як його написати та і що це?

Ось, до речі, скомпільований файл.

Post's attachments

i386.zip 92.15 kb, 303 downloads since 2016-03-03 

27

Re: Драйвер - як його написати та і що це?

Підозрюю, що extern «C» треба робити тільки для тих функцій, які будуть викликатися ззовні вашого коду. Функції, які викликаєте тільки ви самі, можна так не позначати.

Подякували: Дмитро-Чебурашка1

Re: Драйвер - як його написати та і що це?

Дуже дякую!