Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Драйверы Windows режима ядра, как это делается в Delphi 
:(
    Опции темы
Riply
Дата 11.9.2008, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



ama_kid, никак не могу понять:
Вот пишем мы лог из Dispatch функций.
А на чем основана наша уверенность в том, что это потоко-безопасно ?
PM MAIL   Вверх
ama_kid
Дата 11.9.2008, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Цитата(Riply @  11.9.2008,  11:19 Найти цитируемый пост)
на чем основана наша уверенность в том, что это потоко-безопасно ?
Хм... Для начала два встречных вопроса:
1) Я где-нибудь это утверждал?
2) Я где-нибудь использовал потоки?
Естественно, разработка многопоточных приложений может наложить свой отпечаток, в том числе и в режиме ядра, но все-таки это не является предметом рассмотрения в даной статье... Ну а ответом на поставленный вопрос, думаю, может служить тот факт, что посылка запросов IRP_MJ_READ\WRITE\DEVICE_CONTROL осуществляется синхронно, т.е. системный менеджер запросов не пошлет драйверу следующий IRP-пакет до тех пор, пока им не будет обработан предыдущий. Поэтому, допустим, вызов ReadFile из одного потока при обработке ReadFile из другого потока вызовет просто задержку на исполнение первого вызова. Отчасти поэтому и не рекомендуется задерживать обработку IRP-пакетов (а на высоких уровнях приоритета - вообще нельзя) - т.к. это приводит к performance reducing...


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Riply
Дата 11.9.2008, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(ama_kid @  11.9.2008,  14:01 Найти цитируемый пост)
1) Я где-нибудь это утверждал?


Это смотря что считать утверждением  smile 
Я посчитала, что раз ты не побеспокоился о потоко-безопасности,
значит считаешь, что это излишне. Вот я и пыталась понять на чем это заключение основано  smile 

Цитата(ama_kid @  11.9.2008,  14:01 Найти цитируемый пост)
Ну а ответом на поставленный вопрос, думаю, может служить тот факт, что посылка запросов IRP_MJ_READ\WRITE\DEVICE_CONTROL осуществляется синхронно, т.е. системный менеджер запросов не пошлет драйверу следующий IRP-пакет до тех пор, пока им не будет обработан предыдущий.


Спасибо. Именно это меня и интересовало.
Т.е. сколько бы приложений одновременно не открыло наше устройство для связи с драйвером
и с какой интенсивностью они бы ни читали(писали) мы будем получать только по одному запросу
и пока его не обработаем, следующий нам никто не даст.
Я правильно поняла ?

PM MAIL   Вверх
ama_kid
Дата 11.9.2008, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Цитата(Riply @  11.9.2008,  15:20 Найти цитируемый пост)
ты не побеспокоился о потоко-безопасности
Да на таком уровне и беспокоиться не надо - BSOD быстренько бы обо всём напомнил  smile 
Цитата(Riply @  11.9.2008,  15:20 Найти цитируемый пост)
Я правильно поняла ?
вполне  smile





--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Riply
Дата 12.9.2008, 04:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(ama_kid @  9.9.2008,  18:54 Найти цитируемый пост)
Цитата(Riply @  9.9.2008,  18:24 )
какой из способов работы с памятью лучше всего подходит
для этого случая

Конкретно для этого случая мне было удобнее использовать то, что я использовал 


И очень похоже, что ты оказался прав в своем выборе smile

Вот что гласит MSDN:
To allocate I/O buffer space, the best memory allocation routines to use are MmAllocateNonCachedMemory, MmAllocateContiguousMemorySpecifyCache, AllocateCommonBuffer (if the driver's device uses bus-master DMA or a system DMA controller's auto-initialize mode), or ExAllocatePoolWithTag. 

Nonpaged pool typically becomes fragmented as the system runs, so a driver's DriverEntry routine should call these routines to set up any long-term I/O buffers the driver needs. Each of these routines, except ExAllocatePoolWithTag, allocates memory that is aligned on a processor-specific boundary (determined by the processor's data-cache-line size) to provide best performance. 




Это сообщение отредактировал(а) Riply - 12.9.2008, 04:29
PM MAIL   Вверх
Riply
Дата 16.9.2008, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



ama_kid,  что-то мне не удается найти в ntoskrnl.lib ничего похожего
на KeGetCurrentIrql :(

Может она называется там совсем по-другому ?
Подскажи, пожалуйста, как ее импортировать ?




PM MAIL   Вверх
ama_kid
Дата 16.9.2008, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Цитата(Riply @  16.9.2008,  19:18 Найти цитируемый пост)
что-то мне не удается найти в ntoskrnl.lib ничего похожего
на KeGetCurrentIrql :(
Потому что она импортируется из wdm.lib. Смотри аттач (а по-хорошему, просто поставь себе DDK  smile )

Это сообщение отредактировал(а) ama_kid - 16.9.2008, 19:12

Присоединённый файл ( Кол-во скачиваний: 36 )
Присоединённый файл  wdm.lib 186,21 Kb


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Riply
Дата 16.9.2008, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(ama_kid @  16.9.2008,  19:11 Найти цитируемый пост)
Потому что она импортируется из wdm.lib. Смотри аттач 


Спасибо. Скачала, буду смотреть.

Цитата(ama_kid @  16.9.2008,  19:11 Найти цитируемый пост)
а по-хорошему, просто поставь себе DDK  


С DDK мы еще не знакомы. Пока не разобралась с какой стороны к нему подходить smile

PM MAIL   Вверх
Riply
Дата 21.9.2008, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



ama_kid

Хочу вернутся к вопросу потоко-безопасности.
Пару раз заметила, что при записи лога KbdIntcpt (правда чуть переделанного smile идет
искажение информации, причем на определенных сообщениях. Редко но бывает.
Тогда решила добавить в лог ThreadID (первый столбец во второй таблице) 
и посмотреть в каком порядке добавляются записи.

Выдержка из лога Dbgview:
00000034  11:43:50  DriverRead _ 0 0 0    
00000035  11:43:50  DriverRead IoCallDriver 103 0 0    
-->00000036  11:43:54  DriverUnload _ 0 0 0    
00000037  11:43:56  DRIVER_NAME : DriverReadCallBack    
00000038  11:43:56  DriverUnload KeWaitForSingleObject 0 0 0    
00000039  11:43:56  DriverUnload ZwClose 0 0 0    
00000040  11:43:56  DriverRead _ 0 0 0    
00000041  11:43:56  DriverUnload IoDeleteSymbolicLink 0 0 0    
00000042  11:43:56  DriverRead IoCallDriver 103 0 0    
00000043  11:43:56  DriverUnload IoDetachDevice 0 0 2262795872    
00000044  11:43:56  DriverUnload IoDeleteDevice 0 0 2240838328    
00000045  11:43:56  SnakeLog Finalizate 0 43 1024    

Соответствующие строчки из лога KbdIntcpt:
0000000748    21.09  07:43:50.500 DriverRead    IoCallDriver    Overlapped I/O operation is in progress ( $000003E5 )    0000000000    0000000000    0000000025    0000000046
-->0000000052    21.09  07:43:54.062 DriverUnload    _    The operation completed successfully    0000000000    0000000000    0000000026    0000000047
0000000052    21.09  07:43:56.593 DriverUnload    KeWaitForSingleObject    The operation completed successfully    0000000000    0000000000    0000000027    0000000048
0000000052    21.09  07:43:56.593 DriverUnload    ZwClose    The operation completed successfully    0000000000    0000000000    0000000028    0000000049
0000000748    21.09  07:43:56.593 DriverRead    IoCallDriver    Overlapped I/O operation is in progress ( $000003E5 )    0000000000    0000000000    0000000031    0000000051
0000000052    21.09  07:43:56.593 DriverUnload    IoDetachDevice    The operation completed successfully    0000000000    2262795872    0000000032    0000000052
0000000052    21.09  07:43:56.593 DriverUnload    IoDeleteDevice    The operation completed successfully    0000000000    2240838328    0000000033    0000000053
0000000052    21.09  07:43:56.593 SnakeLog    Finalizate    The operation completed successfully    0000000043    0000001024    0000000034    0000000054

"-->"    - помечен вход в процедуру DriverUnload
Видно, что паралельно с ней у нас отрабатывает и процедура DriverRead,
причем работают они "из разных потоков" (ID одного - 52, другого - 748).
Т.е. у нас получается следующая последовательность действий:
DriverUnload -->   KeWaitForSingleObject
DriverUnload -->   ZwClose
DriverRead --> входим в процедуру
DriverUnload -->   IoDeleteSymbolicLink
DriverRead --> IoCallDriver
DriverUnload -->   IoDetachDevice
DriverUnload -->   IoDeleteDevice

Вот такие пироги.

P.S.
 Очень надеюсь, что ты найдешь ошибку в рассуждениях и мне не придется
 разбираться еще и потоко-безопасностью,  вместо похода на дискотеку smile

P.P.S.
 У меня еще возникли вопросы по работе с памятью, но это после того как с этим разберемся smile

Добавлено через 5 минут и 1 секунду
Вот черт. У меня такие аккуратные таблички были, а тут все съехало.
Sorry. 
Надеюсь они стали не очень нечитабельны  smile 
PM MAIL   Вверх
Riply
Дата 23.9.2008, 07:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Если кому интересно...  smile

Попробовала чуть более детально разобраться с нашей потоко-безопасностью.
Вот что получилось:
Для синхронизации выбрала (после очень долгих и тяжких раздумий) объект ERESOURCE.
(Выбирала с учетом своих планов, так что кому-то может лучше подойдут объекты другого типа)
Эффект искажения данных в логе исчез сразу после заключения 
"логовых" функций в "критические обертки".
Для проверки, что одновременная запись в лог разными нитями мне не померещилась
в кошмарном сне smile, чуть изменила стандартный код вхождения в критический регион на нечто такое:

Код

function Test_Lock(const pLock: PVOID; const WaitResource: BOOLEAN): BOOLEAN; stdcall;
begin
 KeEnterCriticalRegion;
 Result := ExAcquireResourceExclusiveLite(pLock, WaitResource);
 if not Result then KeLeaveCriticalRegion;
end;

И в начале процедуры записи в лог:

var
 IsEmpty: Boolean;
begin
 IsEmpty := Test_Lock(pLockFile, False);
 if IsEmpty or Test_Lock(pLockFile, True) then
  try
 /// Если IsEmpty, к сообщению добавляем "Free" иначе "Locked(!)"

Вот выдержка из лога Dbgview:
 
00000043   07:48:45.484   DriverRead IoCallDriver 103 0 Free    
00000044   07:48:45.562   ReadCompleteCallback    
00000045   07:48:45.562   DriverRead _ 0 0 Free    
00000046   07:48:45.562   DriverRead IoCallDriver 103 0 Free    
00000047   07:48:48.718   DriverUnload _ 0 0 Free    
00000048   07:48:50.859   ReadCompleteCallback    
00000049   07:48:50.859   DriverUnload KeWaitForSingleObject 0 0 Free    
00000050   07:48:50.859   DriverUnload ZwClose 0 0 Free    
00000051   07:48:50.859   DriverRead _ 0 0 Locked(!)    
00000052   07:48:50.859   DriverUnload IoDeleteSymbolicLink 0 0 Locked(!)    
00000053   07:48:50.859   DriverRead IoCallDriver 103 0 Locked(!)    
00000054   07:48:50.859   DriverUnload IoDetachDevice 0 0 Free    
00000055   07:48:50.859   DriverUnload IoDeleteDevice 0 0 Free    
00000056   07:48:50.859   LatchFile LatchFile_Finalizate 0 38 1024


Как мне кажется, из нее (выдержки) видно как происходит борьба двух нитей за ресурс smile

P.S.
 То, что мне помогло использование ERESOURCE (это утверждение основано на отсутствии 
 BSOD в течении трех часов smile), вовсе не означает, что путь правильный.
 Требуется более тщательная проверка.    
PM MAIL   Вверх
ama_kid
Дата 29.9.2008, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Цитата(Riply @  21.9.2008,  14:10 Найти цитируемый пост)
Очень надеюсь, что ты найдешь ошибку в рассуждениях
Ой, что-то как-то я упустил свою тему из виду, извиняюсь, просто уже несколько дней не заглядывал на форум...  smile 
Имхо, нет в твоих рассуждениях ошибки, насколько я разобрался в той каше, которую ты вывалила smile
Насколько я понял, у тебя вызвал непонятки момент одновременной записи в лог из DriverRead и DriverUnload? Не забывай (или имей ввиду), что функции DriverEntry и DriverUnload - это не функции-диспетчеры, а функции, выполняющиеся в контексте одного из системных потоков (случайным образом выбирается один из потоков процесса SYSTEM). А функции-диспетчеры выполняются в контексте процесса, выполняющего запрос ввода-вывода . А раз так - то для синхронизации между функциями-диспетчерами и системным потоком конечно нужно использовать объекты синхронизации...

Кроме того, меня смутила твоя фраза про "немного переделанный вариант" KbdIntcpt. Насколько я понял, ты ввела Overlapped-режим? Если я правильно помню - то отложенные операции выполняются тоже в контексте системного потока (аналогично callback-функциям), поэтому между двумя системными потоками тоже неплохо бы вводить синхронизацию при использовании ими общих ресурсов  smile 


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
microxa
Дата 2.12.2008, 05:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 2.12.2008

Репутация: 1
Всего: 1



hi, all smile
Относительно темы delphi драйверов...

Надо отметить что некоторым недостатком является  сборка драйверов из obj-ектников, или использованием сторонних тулз (omf2d, m$-link).

Вобщем куда удобней использовать собственный линкер delphi, устраняя некоторые неровности в производимых им PE dll-ках, таким вот напильником: 

Код

{$apptype console} {$H+}
program DrvConv; uses windows, imagehlp;
var 
    img: PLoadedImage; Section: PImageSectionHeader;
    dwHeaderSum, dwCorrectSum : dword;  
    str: string; i: integer; p0: ^integer; 

begin

    str:= ParamStr(1); if str = '' then exit;
    img:= ImageLoad(pchar(str), nil); if img := nil then exit;
    MapAndLoad(pchar(str), nil, img, true, false);

for i := 0 to img.NumberOfSections-1 do
begin
    Section:= pointer(integer(img.Sections)+
                          SizeOf(TImageSectionHeader)*i);
    str:= pchar(@Section.Name);

    if str = 'CODE' then Section.Characteristics := $68000020;
    if str = 'DATA' then Section.Characteristics := $C8000040;
    if str = 'BSS'  then Section.Characteristics := $C8000000;

    if str = '.text'  then Section.Characteristics := $68000020;
    if str = '.itext' then Section.Characteristics := $62000020;
    if str = '.data'  then Section.Characteristics := $C8000040;
    if str = '.bss'   then Section.Characteristics := $C8000000;
    if str = '.reloc' then Section.Characteristics := $42000040; 
    if str = '.rsrc'  then Section.Characteristics := $40000040; 
// фикс некорректного (0) начала таблицы импорта (PE имиджи D2-D7) 
    if str = '.idata' then begin 
    p0 := pointer(integer(img.MappedAddress)+Section.PointerToRawData);
    if p0^ = 0 then p0^ := pInteger(integer(p0)+$10)^;
    end;
end;
// Устан. атрибутов драйвера 
    img.FileHeader.OptionalHeader.Subsystem := IMAGE_SUBSYSTEM_NATIVE;
// Установить контрольную сумму (CRC) 
    CheckSumMappedFile (img.MappedAddress, img.SizeOfImage, 
                             @dwHeaderSum, @dwCorrectSum );

    img.FileHeader.OptionalHeader.CheckSum := dwCorrectSum;

    ImageUnload (img);  
    writeln ('DLL updated')
end.


Дабы компиль не напихал вредных зависимостей, разюмеется для сборки необходимы минимальные System/Sysinit

Код

// сборка: Dcc32 -b -y System.pas
unit System; 
{$H-,I-,S-,L-}
interface

type

  HRESULT = type LongWord;  
  THandle = LongWord;
  TVarRec = record
  end;
  PByte         = ^Byte;
  PCardinal     = ^Cardinal;
  PPointer      = ^Pointer;
  PGUID = ^TGUID;
  TGUID = record
  end;
  PWideString = ^WideString;
  PInitContext = ^TInitContext;
  TInitContext = record
  end;

procedure _Halt0;
procedure _InitLib;
procedure _DoneExcept;
procedure _HandleFinally;
procedure _HandleAnyException;

implementation
          uses sysinit;

procedure _InitLib;
asm pop eax
    leave // kill internal stack frame
    push eax
end;

procedure _HandleAnyException;
asm mov esp,[esp+8]       // restore stack ptr
    pop dword ptr fs:0    // restore prev SEH frame
    pop  ebp              // get callback address 
    xchg ebp,[esp]        // restore ebp
    add dword ptr [esp],5 // skip jmp, ret to EXCEPT block 
end;

procedure _DoneExcept; 
asm 
end;

procedure _HandleFinally;
asm jmp   _HandleAnyException
end;

procedure _Halt0; 
asm 
end;

end.


Код

unit SysInit;

interface
var
  TlsIndex:Integer;          
  TlsLast: Byte;
  PtrToNil:Pointer = nil;

implementation
end.


Особености реализации модулей позволяют использовать блоки try/except  (хотя от всех видов исключений (например GPF) - они не спасут). 

Ну и собственно как использовать:

Код

Library MyDrv;
...
function DriverEntry (DrvObj: PDRIVER_OBJECT; ...
...

asm jmp DriverEntry
end.

удачи smile

PM MAIL   Вверх
Pavia
Дата 6.12.2008, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 6.12.2008

Репутация: нет
Всего: 12



Использую DDDK0004 

Никак не пойму почему bsod. Пробую пообщаться с IO-APIC

Код

    p:=MmMapIoSpace(PHYSICAL_ADDRESS(IOAPIC),4*1024,MmNonCached );
    p[0]:=$10;
    d:=p[$10];
    irp.UserBuffer:=Pointer(d);
    MmUnmapIoSpace(p,4*1024);

вылитает на этих строчках. Может кто подскажет в чем дело?

А еще dbgprint не работает. 
PM MAIL   Вверх
Pavia
Дата 7.12.2008, 03:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 6.12.2008

Репутация: нет
Всего: 12



Судя по всему срыв стека. Такое впечатление что неправильно экспортирую функции.
Код

type  PHYSICAL_ADDRESS = int64;

  DWord=Cardinal;
  PVOID = Pointer;
  {$EXTERNALSYM PVOID}
  PPVOID = ^PVOID;
  {$EXTERNALSYM PPVOID}
  PVOID64 = Pointer;
  {$EXTERNALSYM PVOID64}

  ULONG_PTR = Longword;
  {$EXTERNALSYM ULONG_PTR}

  SIZE_T = ULONG_PTR;
  {$EXTERNALSYM SIZE_T}
  PSIZE_T = ^SIZE_T;
  {$EXTERNALSYM PSIZE_T}

function MmMapIoSpace(PhysicalAddress:PHYSICAL_ADDRESS;NumberOfBytes:SIZE_T; CacheType:DWord):PVoid;stdcall; external NtKernel name 'MmMapIoSpace';
procedure MmUnMapIoSpace(BaseAddress:PVoid;NumberOfBytes:SIZE_T); stdcall; external NtKernel name 'MmUnmapIoSpace';

PM MAIL   Вверх
ReInit
Дата 7.12.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 14.11.2008

Репутация: 1
Всего: 1



ama_kid
Спасибо! Отличная инфа!

microxa
Т.е. ты собираешь ДЛЛ и используешь ее как драйвер?
Какую версию Делфи ты используешь?
Потому что слышал, если собирать МС линкером, то он понимает обьектники только 3-й Делфи, т.к. после 3-й пошел неправильный COFF формат... И спасибо за System/SysInit, я юзал несколько попроще, без поддержки исключений smile
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.2034 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.