Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
Почему драйверы для Windows 8 глючат

Почему драйверы для Windows 8 глючат

30 Апр 2013

Мы проверили пакет Windows 8 Driver Samples, используя анализатор PVS-Studio. И нашли в примерах разнообразные ошибки. Ничего ужасного в этом нет. Ошибки есть везде. Поэтому название звучит громковато. Однако, эти ошибки, действительно, могут представлять опасность. Ведь часто разработчики основывают свои проекты на демонстрационных примерах или заимствуют из них фрагменты кода.

0199_Why_Windows_8_drivers_are_buggy_ru/image1.png

Windows 8 Driver Samples

Windows 8 Driver Samples представляет собой пакет из 283 независимых решений (solutions). Это доставило нам определенную сложность. Не было никаких сил и желания открывать все решения (*.sln файлы) по отдельности и анализировать их. Мы исследовали этот вопрос и выяснили, что мы не одиноки. На форумах достаточно часто встречается вопрос, как можно объединить несколько решений в одно. Решается эта задача относительно просто. Для тех, кто столкнется с ней, мы подготовили вот эту заметку: "Создание общего решения Visual Studio (.sln файл) из нескольких отдельных проектов".

Код, создаваемый программистами Microsoft, является очень качественным. Об этом свидетельствует, например, результат проверки проекта Casablanca. Однако, создание примеров, по всей видимости, является менее приоритетной задачей. Мне кажется, что для этих проектов не используется статический анализ кода и, возможно, ещё какие-то средства контроля качества. Аналогичную ситуацию мы наблюдали с примерами IPP Samples, созданную компанией Intel. Как показали проверки, ошибок там весьма много (проверки: 1, 2, 3).

Наличие ошибок в примерах не так критично, как в конечных приложениях. Тем не менее, ошибка может перекочевать в настоящий проект и доставить неприятности разработчикам. Даже в рамках Windows 8 Driver Samples встретились идентичные ошибки. Причина очевидна - копирование кода из соседнего примера. Точно также эти ошибки будут скопированы в настоящие драйвера.

Итак, давайте посмотрим, что интересного можно найти в Windows 8 Driver Samples. Для анализа мы использовали статический анализатор кода PVS-Studio версии 5.03. Как всегда хочу подчеркнуть, что я выписываю только те места, которые мне показались явно подозрительными. Многие диагностические сообщения я просматривал невнимательно. Если кто-то из разработчиков примеров заинтересуется этой заметкой, то прошу не ограничиваться только информацией, приведенной в ней, и выполнить анализ более тщательно.

Примечание. Visual Studio не предоставляет API для проектов, являющихся расширением стандартной проектной модели Visual C++. Именно к ним относятся проекты для создания драйверов. Поэтому потребуется дополнительная настройка PVS-Studio, чтобы проверить драйверы. А именно: необходимо интегрировать PVS-Studio с MSBuild. Подробнее про режим интеграции с MSBuild рассказано здесь:

Лишняя точка с запятой ';'

NDIS_STATUS HwSetPowerMgmtMode(....)
{
  ....
  if (!HW_MULTIPLE_MAC_ENABLED(Hw) &&
      (PMMode->dot11PowerMode != dot11_power_mode_unknown));
  {
    NdisMoveMemory(&Hw->MacState.PowerMgmtMode, PMMode,
       sizeof(DOT11_POWER_MGMT_MODE));
    HalSetPowerMgmtMode(Hw->Hal, PMMode);
  }
  ....
}

V529 Odd semicolon ';' after 'if' operator. hw_mac.c 95

Обратите внимание на точку с запятой вот здесь: "...unknown));". В результате, код ниже будет выполняться всегда, независимо от условия.

Плохой ASSERT

VOID MPCreateProgrammableFilter(....)
{
  ....
  ASSERT (0 < dwMaskSize <5);
  ....
}

V562 It's odd to compare 0 or 1 with a value of 5: 0 < dwMaskSize < 5. nic_pm.c 825

Комментарии здесь излишни.

Подозрительная функция инициализации

NTSTATUS UartInitContext(_In_ WDFDEVICE Device)
{
  ....
  pDevExt->WdfDevice;
  ....
}

V607 Ownerless expression 'pDevExt->WdfDevice'. uart16550pc.cpp 58

Мне кажется, в функции UartInitContext () забыли инициализировать переменную 'pDevExt->WdfDevice'. Чем её следует инициализировать, я затрудняюсь сказать.

Опечатка

BOOLEAN DsmpFindSupportedDevice(....)
{
  WCHAR tempString[32];
  ....
  tempString[(sizeof(tempString) /
              sizeof(tempString)) - 1] = L'\0';
  ....
}

V501 There are identical sub-expressions 'sizeof (tempString)' to the left and to the right of the '/' operator. utils.c 931

Из-за опечатки терминальный ноль будет записан не в конец строки, а в её начало. Размер буфера sizeof(tempString) должен делиться на размер одного символа. Вместо этого, он делится сам на себя. Правильный код:

tempString[(sizeof(tempString) /
  sizeof(tempString[0])) - 1] = L'\0';

Забыли, что строка состоит из символов типа WCHAR

HRESULT CDot11SampleExtUI::CreateSecurityProperties(....)
{
  ....
  WCHAR wbuf[128];
  ....
  ZeroMemory(wbuf, 128);
  ....
}

V512 A call of the 'memset' function will lead to underflow of the buffer 'wbuf'. ihvsampleextui.cpp 288

Функция ZeroMemory() очистит только половину буфера 'wbuf'. Поскольку этот код относится к функции 'CreateSecurityProperties()', то, наверное, можно говорить о потенциальной уязвимости. Корректный код:

ZeroMemory(wbuf, 128 * sizeof(WCHAR));

Другая ошибка по этой же тематике:

typedef struct _DEVICE_INFO
{
  ....
  WCHAR UnicodeSourceIp[MAX_LEN];
  WCHAR UnicodeDestIp[MAX_LEN];
  ....
} DEVICE_INFO, *PDEVICE_INFO;

PDEVICE_INFO FindDeviceInfo(....)
{
  ....
  PDEVICE_INFO    deviceInfo = NULL;
  ....
  memcpy(deviceInfo->UnicodeSourceIp,
         InputInfo->SourceIp, MAX_LEN);
  memcpy(deviceInfo->UnicodeDestIp,
         InputInfo->DestIp, MAX_LEN);
  ....       
}

V512 A call of the 'memcpy' function will lead to underflow of the buffer 'deviceInfo->UnicodeSourceIp'. testapp.c 729

V512 A call of the 'memcpy' function will lead to underflow of the buffer 'deviceInfo->UnicodeDestIp'. testapp.c 730

Копируем только половину строки. Анализатор выдавал и другие диагностические сообщения V512, но чтобы понять, есть там ошибка или нет, нужно вникать в код внимательнее. А я не могу. У меня очередь из проектов, которые хочется посмотреть.

Повторная проверка

Я затрудняюсь привести фрагмент кода. В нём используются такие длинные имена, как "WFPSAMPLER_CALLOUT_BASIC_ACTION_BLOCK_AT_INBOUND_MAC_FRAME_NATIVE". Оформление статьи на нашем сайте viva64.com сломается от таких длинных строк. Ограничусь словесным описанием. В функции KrnlHlprExposedCalloutToString() можно найти код вида:

else if (A == &inbound)
  str = "inbound";
else if (A == &inbound)
  str = "outbound";

Этот код не имеет смысла, так как второй оператор 'if' никогда не выполнится. Код встречается в файле helperfunctions_exposedcallouts.cpp несколько раз. Видимо, причина тому copy-paste. Перечислю все эти места:

  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 556, 558. helperfunctions_exposedcallouts.cpp 556
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 649, 651. helperfunctions_exposedcallouts.cpp 649
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 742, 744. helperfunctions_exposedcallouts.cpp 742
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 835, 837. helperfunctions_exposedcallouts.cpp 835
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 908, 910. helperfunctions_exposedcallouts.cpp 908
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 981, 983. helperfunctions_exposedcallouts.cpp 981
  • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1055, 1057. helperfunctions_exposedcallouts.cpp 1055

А вот другой случай повторной проверки.

HRESULT CSensor::HandleSetReportingAndPowerStates(....)
{
  ....
  else if (SENSOR_POWER_STATE_LOW_POWER == ulCurrentPowerState)
  {
    Trace(TRACE_LEVEL_ERROR,
      "%s Power State value is not correct = LOW_POWER, "
      "hr = %!HRESULT!", m_SensorName, hr);
  }
  else if (SENSOR_POWER_STATE_LOW_POWER == ulCurrentPowerState)
  {
    Trace(TRACE_LEVEL_ERROR,
      "%s Power State value is not correct = FULL_POWER, "
      "hr = %!HRESULT!", m_SensorName, hr);
  }
  ....
}

V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 5641, 5645. sensor.cpp 5641

Мне кажется, вторая проверка должна выглядеть так:

else if (SENSOR_POWER_STATE_FULL_POWER == ulCurrentPowerState)

"Одноразовый" цикл

NDIS_STATUS AmSetApBeaconMode(....)
{
  ....
  while (BeaconEnabled != AssocMgr->BeaconEnabled)
  {
    ndisStatus = ....;
    if (NDIS_STATUS_SUCCESS != ndisStatus)
    {
      break;
    }
    AssocMgr->BeaconEnabled = BeaconEnabled;
    break;
  }
  ....
}

V612 An unconditional 'break' within a loop. ap_assocmgr.c 1817

Тело цикла выполняется не больше одного раза. Мне кажется, оператор 'break' в конце является лишним.

Неправильный swap?

NTSTATUS FatSetDispositionInfo (....)
{
  ....
  TmpChar = LocalBuffer[0];
  LocalBuffer[0] = TmpChar;
  ....
}

V587 An odd sequence of assignments of this kind: A = B; B = A;. Check lines: 2572, 2573. fileinfo.c 2573

Странный и бессмысленный код. Наверное, хотели обменять значение элемента массива "LocalBuffer[0]" с другой переменной. Но получилось что-то совсем не то.

Условие ни на что не влияет

NDIS_STATUS Hw11QueryDiversitySelectionRX(....)
{
  //
  // Determine the PHY that the user wants to query
  //
  if (SelectedPhy)
    return HwQueryDiversitySelectionRX(HwMac->Hw, 
              HwMac->SelectedPhyId, 
              MaxEntries, 
              Dot11DiversitySelectionRXList
              );
  else
    return HwQueryDiversitySelectionRX(HwMac->Hw,
              HwMac->SelectedPhyId, 
              MaxEntries, 
              Dot11DiversitySelectionRXList
              );
}

V523 The 'then' statement is equivalent to the 'else' statement. hw_oids.c 1043

Значение переменной 'SelectedPhy' не важно. Всегда выполняется одно и то же действие. Я не уверен, что это ошибка. Однако, код очень подозрительный. Вот другие подозрительные места:

  • V523 The 'then' statement is equivalent to the 'else' statement. fail_driver1.c 188
  • V523 The 'then' statement is equivalent to the 'else' statement. simgpio_i2c.c 2253
  • V523 The 'then' statement is equivalent to the 'else' statement. simgpio.c 2181

Неправильное восстановление настроек

Чтобы временно отключить предупреждения, следует использовать последовательность директив следующего вида:

#pragma warning(push)
#pragma warning(disable: XXX)
....
#pragma warning(pop)

Однако часто поступают более просто:

#pragma warning(disable:XXX)
....
#pragma warning(default:XXX)

Такой подход неверен. Мог быть выставлен режим выдачи предупреждений, отличный от режима по умолчанию. В результате, после #pragma warning(default:XXX) могут выдаться лишние предупреждения или наоборот они будут скрыты от программиста.

В Windows 8 Driver Samples можно найти несколько таких мест, где неправильно подавляются предупреждения. Пример:

// disable nameless struct/union warnings
#pragma warning(disable:4201) 
#include <wdf.h>
#pragma warning(default:4201)

V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 23, 25. common.h 25

Перечислю остальные места, где неаккуратно подавляются предупреждения:

  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 25, 29. protnotify.cpp 29
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 27, 29. common.h 29
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 30, 34. hidkmdf.c 34
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 446, 450. kbfiltr.c 450
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 48, 58. trace.h 58
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 175, 186. reg9656.h 186
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 3, 8. precomp.h 8
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 118, 128. trace.h 128
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 27, 33. precomp.h 33
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 57, 79. usb_hw.h 79
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 2497, 2499. pnp.c 2499
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 35, 38. hidumdf.c 38
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 47, 54. kmdf_vdev_sample.h 54
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 21, 25. kmdf_vdev.h 25
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 57, 79. usb_hw.h 79
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 374, 1099. uvcdesc.h 1099
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 566, 575. uvcview.c 575
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 62, 84. usb_hw.h 84
  • V665 Possibly, the usage of '#pragma warning(default: X)' is incorrect in this context. The '#pragma warning(push/pop)' should be used instead. Check lines: 589, 604. wsksmple.c 604

Потенциальный вечный цикл

VOID HwFillRateElement(....)
{
  UCHAR i, j;
  ....
  for (i = 0; (i < basicRateSet->uRateSetLength) &&
              (i < 256); i++)
  {
    rate[i] = 0x80 | basicRateSet->ucRateSet[i];
  }
  ....
}

V547 Expression 'i < 256' is always true. The value range of unsigned char type: [0, 255]. hw_mac.c 1946

Здесь возможен вечный цикл. Переменная 'i' имеет тип UCHAR. Значит, её диапазон значений от 0 до 255. Эти значения всегда меньше 256. Получается, что цикл ограничивается только условием (i < basicRateSet->uRateSetLength).

Схожую ошибку можно увидеть и здесь:

VOID HwFillRateElement(....)
{
  ....
  UCHAR rate[256];
  UCHAR rateNum;
  ....
  if (rateNum == sizeof(rate) / sizeof(UCHAR))
    break;
  ....  
}

V547 Expression is always false. The value range of unsigned char type: [0, 255]. hw_mac.c 1971

Выражение "sizeof(rate) / sizeof(UCHAR)" равно 256. Переменная 'rateNum' имеет тип UCHAR. Это значит, что условие никогда не выполнится.

Потенциальное разыменование нулевого указателя

Указатели принято проверять на равенство нулю. Но я с уверенностью могу сказать, что часто это делается халтурно. То есть проверка есть, а толку от неё нет. Пример такой проверки:

HRESULT CFileContext::GetNextSubscribedMessage()
{
  ....
  m_pWdfRequest = pWdfRequest;
  m_pWdfRequest->MarkCancelable(pCallbackCancel);
  if (m_pWdfRequest != NULL)
  {
    CompleteOneArrivalEvent();
  }
  ....
}

V595 The 'm_pWdfRequest' pointer was utilized before it was verified against nullptr. Check lines: 266, 267. filecontext.cpp 266

Указатель 'm_pWdfRequest' используется для вызова функции MarkCancelable(). А затем вдруг вспомнили, что он может быть равен нулю, и написали проверку: "if (m_pWdfRequest != NULL)".

Такой код чаще всего возникает в процессе рефакторинга. Строки перемещаются, дописываются новые выражения. И бывает, что проверка указателя оказывается ниже, чем расположено первое использование указателя.

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

Список диагностических сообщений:

  • V595 The 'pAdapterCommon' pointer was utilized before it was verified against nullptr. Check lines: 456, 477. adapter.cpp 456
  • V595 The 'PortStream' pointer was utilized before it was verified against nullptr. Check lines: 111, 123. rtstream.cpp 111
  • V595 The 'pncLock' pointer was utilized before it was verified against nullptr. Check lines: 85, 112. netcfgapi.cpp 85
  • V595 The 'm_pInterruptSync' pointer was utilized before it was verified against nullptr. Check lines: 707, 724. miniport.cpp 707
  • V595 The 'deviceExtension' pointer was utilized before it was verified against nullptr. Check lines: 798, 816. cdrom.c 798
  • V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines: 9614, 9621. class.c 9614
  • V595 The 'OffloadReadContext' pointer was utilized before it was verified against nullptr. Check lines: 13704, 13706. class.c 13704
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'instanceContext' pointer was utilized before it was verified against nullptr. Check lines: 211, 237. support.c 211
  • V595 The 'BiosCodeSpace' pointer was utilized before it was verified against nullptr. Check lines: 8229, 8249. lsi_u3.c 8229
  • V595 The 'pAdapterCommon' pointer was utilized before it was verified against nullptr. Check lines: 293, 319. adapter.cpp 293
  • V595 The 'm_AdapterCommon' pointer was utilized before it was verified against nullptr. Check lines: 217, 223. basetopo.cpp 217
  • V595 The 'm_AdapterCommon' pointer was utilized before it was verified against nullptr. Check lines: 200, 208. basewave.cpp 200
  • V595 The 'port' pointer was utilized before it was verified against nullptr. Check lines: 216, 234. common.cpp 216
  • V595 The 'miniport' pointer was utilized before it was verified against nullptr. Check lines: 226, 239. common.cpp 226
  • V595 The 'port' pointer was utilized before it was verified against nullptr. Check lines: 404, 412. adapter.cpp 404
  • V595 The 'm_AdapterCommon' pointer was utilized before it was verified against nullptr. Check lines: 216, 222. basetopo.cpp 216
  • V595 The 'targetPortGroupEntry' pointer was utilized before it was verified against nullptr. Check lines: 534, 541. dsmmain.c 534
  • V595 The 'dsmContext' pointer was utilized before it was verified against nullptr. Check lines: 364, 382. intrface.c 364
  • V595 The 'passThrough' pointer was utilized before it was verified against nullptr. Check lines: 635, 648. utils.c 635
  • V595 The 'passThrough' pointer was utilized before it was verified against nullptr. Check lines: 1537, 1550. utils.c 1537
  • V595 The 'passThrough' pointer was utilized before it was verified against nullptr. Check lines: 1747, 1760. utils.c 1747
  • V595 The 'ioStatus' pointer was utilized before it was verified against nullptr. Check lines: 5236, 5247. utils.c 5236
  • V595 The 'devInfo' pointer was utilized before it was verified against nullptr. Check lines: 3227, 3229. wmi.c 3227
  • V595 The 'pdi' pointer was utilized before it was verified against nullptr. Check lines: 575, 583. codec.c 575
  • V595 The 'AssocMgr' pointer was utilized before it was verified against nullptr. Check lines: 786, 789. ap_assocmgr.c 786
  • V595 The 'newExtApPort' pointer was utilized before it was verified against nullptr. Check lines: 87, 101. ap_main.c 87
  • V595 The 'ApPort' pointer was utilized before it was verified against nullptr. Check lines: 3068, 3070. ap_oids.c 3068
  • V595 The 'HandleContext' pointer was utilized before it was verified against nullptr. Check lines: 2741, 2762. ncdirnotify.c 2741
  • V595 The 'pHvl' pointer was utilized before it was verified against nullptr. Check lines: 277, 297. hvl_main.c 277
  • V595 The 'pNextActiveContext' pointer was utilized before it was verified against nullptr. Check lines: 914, 916. hvl_main.c 914
  • V595 The 'pNextActiveContext' pointer was utilized before it was verified against nullptr. Check lines: 987, 989. hvl_main.c 987
  • V595 The 'pNextCtx' pointer was utilized before it was verified against nullptr. Check lines: 874, 894. hvl_main.c 874
  • V595 The 'pVNic' pointer was utilized before it was verified against nullptr. Check lines: 559, 584. vnic_main.c 559
  • V595 The 'pExReq' pointer was utilized before it was verified against nullptr. Check lines: 1563, 1575. vnic_main.c 1563
  • V595 The 'pJoinReq' pointer was utilized before it was verified against nullptr. Check lines: 241, 259. vnic_queue.c 241
  • V595 The 'pChSwReq' pointer was utilized before it was verified against nullptr. Check lines: 439, 447. vnic_queue.c 439
  • V595 The 'newPort' pointer was utilized before it was verified against nullptr. Check lines: 90, 100. base_port_main.c 90
  • V595 The 'newPort' pointer was utilized before it was verified against nullptr. Check lines: 1379, 1390. helper_port_main.c 1379
  • V595 The 'adapter' pointer was utilized before it was verified against nullptr. Check lines: 168, 196. mp_pnp.c 168
  • V595 The 'newAdapter' pointer was utilized before it was verified against nullptr. Check lines: 458, 472. mp_pnp.c 458
  • V595 The 'portRegInfo' pointer was utilized before it was verified against nullptr. Check lines: 153, 166. port_main.c 153
  • V595 The 'newPort' pointer was utilized before it was verified against nullptr. Check lines: 268, 280. port_main.c 268
  • V595 The 'pso24' pointer was utilized before it was verified against nullptr. Check lines: 338, 352. brush.c 338
  • V595 The 'newHw' pointer was utilized before it was verified against nullptr. Check lines: 338, 358. hw_main.c 338
  • V595 The 'Hw->Hal' pointer was utilized before it was verified against nullptr. Check lines: 605, 623. hw_main.c 605
  • V595 The 'UseCoalesce' pointer was utilized before it was verified against nullptr. Check lines: 1760, 1781. hw_send.c 1760
  • V595 The 'm_pWdfRequest' pointer was utilized before it was verified against nullptr. Check lines: 248, 250. filecontext.cpp 248
  • V595 The 'pDOMSnapshot' pointer was utilized before it was verified against nullptr. Check lines: 711, 736. gdlsmpl.cpp 711
  • V595 The '* ppDOMSnapshot' pointer was utilized before it was verified against nullptr. Check lines: 833, 842. gdlsmpl.cpp 833
  • V595 The 'm_pRootDocument' pointer was utilized before it was verified against nullptr. Check lines: 163, 168. xmlhandler.cxx 163
  • V595 The 'pNewNode' pointer was utilized before it was verified against nullptr. Check lines: 403, 411. xmlhandler.cxx 403
  • V595 The 'pNewNode' pointer was utilized before it was verified against nullptr. Check lines: 625, 655. xmlhandler.cxx 625
  • V595 The 'pNewAttribute' pointer was utilized before it was verified against nullptr. Check lines: 634, 646. xmlhandler.cxx 634
  • V595 The 'pCurrentNode' pointer was utilized before it was verified against nullptr. Check lines: 883, 913. xmlhandler.cxx 883
  • V595 The 'pAttribute' pointer was utilized before it was verified against nullptr. Check lines: 993, 1001. xmlhandler.cxx 993
  • V595 The 'pAttrMap' pointer was utilized before it was verified against nullptr. Check lines: 982, 1011. xmlhandler.cxx 982
  • V595 The 'pAttrNode' pointer was utilized before it was verified against nullptr. Check lines: 990, 1013. xmlhandler.cxx 990
  • V595 The 'ppszDisplayName' pointer was utilized before it was verified against nullptr. Check lines: 1734, 1752. features.cpp 1734
  • V595 The 'ppszDisplayName' pointer was utilized before it was verified against nullptr. Check lines: 1903, 1921. features.cpp 1903
  • V595 The 'pszTemp' pointer was utilized before it was verified against nullptr. Check lines: 353, 366. util.c 353
  • V595 The 'pszTimeout' pointer was utilized before it was verified against nullptr. Check lines: 713, 723. util.c 713
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 193, 201. driver.cpp 193
  • V595 The 'queue' pointer was utilized before it was verified against nullptr. Check lines: 70, 79. queue.cpp 70
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'ctx' pointer was utilized before it was verified against nullptr. Check lines: 521, 545. swapbuffers.c 521
  • V595 The 'trimContext' pointer was utilized before it was verified against nullptr. Check lines: 2454, 2457. common.c 2454
  • V595 The 'trimContext' pointer was utilized before it was verified against nullptr. Check lines: 2579, 2582. common.c 2579
  • V595 The 'trimContext' pointer was utilized before it was verified against nullptr. Check lines: 2568, 2582. common.c 2568
  • V595 The 'pWriteBuffer' pointer was utilized before it was verified against nullptr. Check lines: 682, 707. accelerometerdevice.cpp 682
  • V595 The 'pBuffer' pointer was utilized before it was verified against nullptr. Check lines: 838, 867. accelerometerdevice.cpp 838
  • V595 The 'pBuffer' pointer was utilized before it was verified against nullptr. Check lines: 928, 949. accelerometerdevice.cpp 928
  • V595 The 'pBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1017, 1030. accelerometerdevice.cpp 1017
  • V595 The 'pWriteBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1120, 1134. accelerometerdevice.cpp 1120
  • V595 The 'pWriteBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1291, 1305. accelerometerdevice.cpp 1291
  • V595 The 'myDevice' pointer was utilized before it was verified against nullptr. Check lines: 193, 201. driver.cpp 193
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'deviceInterfaceDetailData' pointer was utilized before it was verified against nullptr. Check lines: 170, 180. sensorcommunication.cpp 170
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 199, 207. driver.cpp 199
  • V595 The 'queue' pointer was utilized before it was verified against nullptr. Check lines: 119, 128. queue.cpp 119
  • V595 The 'queue' pointer was utilized before it was verified against nullptr. Check lines: 1368, 1377. queue.cpp 1368
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 223, 231. umdf_vdev_driver.cpp 223
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'device' pointer was utilized before it was verified against nullptr. Check lines: 206, 214. driver.cpp 206
  • V595 The 'packet' pointer was utilized before it was verified against nullptr. Check lines: 1305, 1312. inspect.c 1305
  • V595 The 'FxRequest' pointer was utilized before it was verified against nullptr. Check lines: 937, 945. device.cpp 937
  • V595 The 'pImageCodecInfo' pointer was utilized before it was verified against nullptr. Check lines: 72, 83. gphelper.h 72
  • V595 The 'pTargetBitmap' pointer was utilized before it was verified against nullptr. Check lines: 314, 329. gphelper.h 314
  • V595 The 'pStreamOut' pointer was utilized before it was verified against nullptr. Check lines: 787, 790. imagefilter.cpp 787
  • V595 The 'pWiaItemWrapper' pointer was utilized before it was verified against nullptr. Check lines: 1590, 1620. imagefilter.cpp 1590
  • V595 The 'pIWiaItemWrapper' pointer was utilized before it was verified against nullptr. Check lines: 2028, 2032. imagefilter.cpp 2028
  • V595 The 'pIWiaItemWrapper' pointer was utilized before it was verified against nullptr. Check lines: 267, 282. segmentation.cpp 267
  • V595 The 'm_pArray' pointer was utilized before it was verified against nullptr. Check lines: 193, 199. basicarray.h 193
  • V595 The 'm_pArray' pointer was utilized before it was verified against nullptr. Check lines: 229, 235. basicarray.h 229
  • V595 The 'pWIADeviceCapability' pointer was utilized before it was verified against nullptr. Check lines: 233, 249. capman.cpp 233
  • V595 The 'pImageCodecInfo' pointer was utilized before it was verified against nullptr. Check lines: 298, 310. fileconv.cpp 298
  • V595 The 'ppOutputStream' pointer was utilized before it was verified against nullptr. Check lines: 413, 437. fileconv.cpp 413
  • V595 The 'ppOutputStream' pointer was utilized before it was verified against nullptr. Check lines: 713, 721. fileconv.cpp 713
  • V595 The 'pwData' pointer was utilized before it was verified against nullptr. Check lines: 1966, 1996. scanjobs.cpp 1966
  • V595 The 'm_pSensorManager' pointer was utilized before it was verified against nullptr. Check lines: 4996, 5017. sensor.cpp 4996
  • V595 The 'wszDataCopy' pointer was utilized before it was verified against nullptr. Check lines: 1320, 1334. basicddi.cpp 1320
  • V595 The 'm_pOemCUIPParam' pointer was utilized before it was verified against nullptr. Check lines: 490, 494. uictrl.cpp 490
  • V595 The 'm_pOemCUIPParam' pointer was utilized before it was verified against nullptr. Check lines: 807, 812. uictrl.cpp 807
  • V595 The 'm_pOemCUIPParam' pointer was utilized before it was verified against nullptr. Check lines: 1083, 1087. uictrl.cpp 1083

Разыменовывание нулевого указателя

Выше мы рассмотрели разыменовывание указателя, который может быть равен нулю. А теперь рассмотрим случай, когда он точно равен нулю.

HRESULT CSensorDDI::OnGetDataFields(....)
{
  ....
  if (nullptr != pSensor)
  {
    ....
  }
  else
  {
    hr = E_POINTER;
    Trace(TRACE_LEVEL_ERROR,
      "pSensor == NULL before getting datafield %!GUID!-%i "
      "value from %s, hr = %!HRESULT!",
      &Key.fmtid, Key.pid, pSensor->m_SensorName, hr);
  }
}

V522 Dereferencing of the null pointer 'pSensor' might take place. sensorddi.cpp 903

В случае, если указатель 'pSensor' равен нулю, то хочется сохранить соответствующую информацию в лог. Однако, попытка взять имя с помощью "pSensor->m_SensorName" явно неудачная идея.

Аналогичная ошибка здесь:

V522 Dereferencing of the null pointer 'pSensor' might take place. sensorddi.cpp 1852

Странный цикл

VOID ReportToString(
   PHID_DATA pData,
   _Inout_updates_bytes_(iBuffSize) LPSTR szBuff,
   UINT iBuffSize
)
{
  ....
  if(FAILED(StringCbPrintf (szBuff,
                iBuffSize,
                "Usage Page: 0x%x, Usages: ",
                pData -> UsagePage)))
  {
    for(j=0; j<sizeof(szBuff); j++)
    {
      szBuff[j] = '\0';
    }
    return;
  }
  ....
}

V604 It is odd that the number of iterations in the loop equals to the size of the 'szBuff' pointer. hclient.c 1688

Обратите внимание на условие остановки цикла "j<sizeof(szBuff)". Очень странно, что цикл выполняется столько раз, сколько байт содержится в указатели (то есть 4 или 8). Скорее всего, здесь должно было быть написано:

for(j=0; j<iBuffSize; j++)

Уязвимость из-за опечатки

bool ParseNumber(....)
{
  ....
  if ((*Value < Bounds.first) || 
      (*Value > Bounds.second))
  {
    printf("Value %s is out of bounds\n", String.c_str());
    false;
  }
  ....
}

V606 Ownerless token 'false'. util.cpp 91

Выполняется проверка, что значение переменной выходит за определенные границы. Это событие должно остановить работу функции, но этого не происходит. Из-за опечатки, вместо "return false;" написано просто "false";

Эту же ошибку можно найти здесь:

V606 Ownerless token 'false'. util.cpp 131

Опечатка в switch

В начале статьи я отметил, что ошибки из примеров имеют тенденцию расползаться в разные стороны. Сейчас я продемонстрирую это на примере. Рассмотрим подозрительный код.

PCHAR DbgDevicePowerString(IN WDF_POWER_DEVICE_STATE Type)
{
  ....
  case WdfPowerDeviceD0:
    return "WdfPowerDeviceD0";
  case PowerDeviceD1:
    return "WdfPowerDeviceD1";
  case WdfPowerDeviceD2:
    return "WdfPowerDeviceD2";
  ....
}

V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. usb.c 450

Скорее всего, вместо "case PowerDeviceD1:" должно быть написано "case WdfPowerDeviceD1:". Имя 'PowerDeviceD1' вообще относится к другому перечисляемому типу (enum).

Так вот, эта ошибка обнаружилась сразу в нескольких проектах. Расползлась с помощью Copy-Paste. Другие места с этой ошибкой:

  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. pcidrv.c 1707
  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. device.c 367
  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. device.c 935
  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. power.c 366
  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. power.c 56
  • V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. kmdf_vdev_pnp.c 727

Число Пи равно 3

NTSTATUS KcsAddTrignometricInstance (....)
{
  ....
  Angle = (double)(Timestamp.QuadPart / 400000) *
          (22/7) / 180;
  ....
}

V636 The '22 / 7' expression was implicitly casted from 'int' type to 'double' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. kcs.c 239

Это странное целочисленное деление. Почему сразу не написать 3? Возможно, правильнее будет написать так: (22.0/7). Тогда результат будет 3.1428.... Кстати, Википедия подсказывает, что дробь 22/7 иногда используется, как приблизительное значение числа Пи. Тогда оно получилось у программиста ОЧЕНЬ приблизительное.

Пережитки старины

Когда-то давно, оператор 'new' возвращал 0, если возникала ошибка выделения памяти. Те времена давно прошли. И теперь согласно стандарту, оператор 'new' генерирует в случае ошибки исключение std::bad_alloc(). Но многие программисты про это не знают или забывают. Или используют свой стародавний код, где такие проверки есть.

Можно подумать, что это не беда. Подумаешь, выполнится лишняя проверка. Но дело в том, что часто в случае ошибки, программа должна выполнить дополнительные действия. Например, освободить память или закрыть файл. Но теперь, при нехватке памяти, возникает исключение. И код, который должен был обработать аварийную ситуацию, остается без дел.

Рассмотрим такой пример:

int SetHwidCallback(....)
{
  ....
  LPTSTR * tmpArray = new LPTSTR[cnt+2];
  if(!tmpArray) {
    goto final;
  }
  ....
final:
  if(hwlist) {
    DelMultiSz(hwlist);
  }
  return result;
}

V668 There is no sense in testing the 'tmpArray' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. cmds.cpp 2016

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

В Windows 8 Driver Samples много мест, где указатель, полученный от оператора 'new' проверяется на равенство нулю. Скорее всего, в большинстве случаев всё будет работать хорошо. Однако, все равно такие места следует внимательно просмотреть. Вот они:

  • V668 There is no sense in testing the 'pINotifyDataObject' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. acallback.cpp 309
  • V668 There is no sense in testing the 'pIAsynchCallback' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. client.cpp 142
  • V668 There is no sense in testing the 'pINotifyDataObject' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. acallback.cpp 226
  • V668 There is no sense in testing the 'pIAsynchCallback' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. asyncnotify.cpp 57
  • V668 There is no sense in testing the 'pClientNotification' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. asyncnotify.cpp 77
  • V668 There is no sense in testing the 'pIAsynchCallback' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. asyncnotify.cpp 102
  • V668 There is no sense in testing the 'pClientNotification' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. asyncnotify.cpp 120
  • V668 There is no sense in testing the 'pNewItem' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. tlist.h 129
  • V668 There is no sense in testing the 'pNewItem' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. tlist.h 158
  • V668 There is no sense in testing the 'pNewItem' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. tlist.h 384
  • V668 There is no sense in testing the 'pNewItem' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. tlist.h 414
  • V668 There is no sense in testing the 'pAudioParamsCopy' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. advendpointproppage.cpp 1004
  • V668 There is no sense in testing the 'pAudioFXParamsCopy' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. swapproppage.cpp 811
  • V668 There is no sense in testing the 'array' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. devcon.cpp 389
  • V668 There is no sense in testing the 'multiSz' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. devcon.cpp 434
  • V668 There is no sense in testing the 'resDesData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dump.cpp 250
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 128
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 185
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. oemcom.cpp 448
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. oemcom.cpp 522
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 128
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 185
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. oemcom.cpp 826
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. oemcom.cpp 903
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. controlqueue.cpp 104
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. readwritequeue.cpp 203
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 65
  • V668 There is no sense in testing the 'instanceId' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 415
  • V668 There is no sense in testing the 'm_Ppd' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 626
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'buffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. socketechoserver.cpp 59
  • V668 There is no sense in testing the 'client' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. socketechoserver.cpp 383
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 63
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 157
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'pMyQueue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 90
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 343
  • V668 There is no sense in testing the 'pConnection' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 208
  • V668 There is no sense in testing the 'm_Luminous' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sauron.cpp 66
  • V668 There is no sense in testing the 'pwszBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ihvsampleextui.cpp 633
  • V668 There is no sense in testing the 'pOemPDEV' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 730
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1795
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1880
  • V668 There is no sense in testing the 'm_pbPayload' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. filecontext.h 48
  • V668 There is no sense in testing the 'm_pszType' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. filecontext.cpp 136
  • V668 There is no sense in testing the 'pbNewPayload' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. filecontext.cpp 596
  • V668 There is no sense in testing the 'pMyPayload' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. filecontext.cpp 627
  • V668 There is no sense in testing the 'pConnection' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. connection.cpp 46
  • V668 There is no sense in testing the 'pMessage' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. connection.cpp 251
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 207
  • V668 There is no sense in testing the 'pszFileNameBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 226
  • V668 There is no sense in testing the 'pMessage' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 571
  • V668 There is no sense in testing the 'pMessage' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 705
  • V668 There is no sense in testing the 'pGDLSampleClassFactory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. gdlsmpl.cpp 255
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. gdlsmpl.cpp 380
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 114
  • V668 There is no sense in testing the 'pOemPDEV' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 732
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1717
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1807
  • V668 There is no sense in testing the 'poempdev' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 329
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 529
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 621
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 474
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 556
  • V668 There is no sense in testing the 'pOemPDEV' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 711
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1690
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 1784
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 472
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 551
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cxx 386
  • V668 There is no sense in testing the 'pOemPT' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cxx 401
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cxx 483
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 115
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 175
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 519
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 601
  • V668 There is no sense in testing the 'pszAngle' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. command.cpp 290
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 396
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 481
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 429
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 511
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 115
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 175
  • V668 There is no sense in testing the 'm_pData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. features.cpp 234
  • V668 There is no sense in testing the 'm_pFeatures' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. features.cpp 984
  • V668 There is no sense in testing the 'pPairs' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. features.cpp 1564
  • V668 There is no sense in testing the 'pUIReplacementCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 162
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 292
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 482
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 564
  • V668 There is no sense in testing the 'p2' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. pixel.cpp 585
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 431
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 513
  • V668 There is no sense in testing the 'poempdev' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 311
  • V668 There is no sense in testing the 'pOemCP' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 854
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 939
  • V668 There is no sense in testing the 'Contexts' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. plx.cpp 442
  • V668 There is no sense in testing the 'Threads' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. plx.cpp 442
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 115
  • V668 There is no sense in testing the 'lpszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 175
  • V668 There is no sense in testing the 'pOemCB' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 616
  • V668 There is no sense in testing the 'pFontCF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. intrface.cpp 698
  • V668 There is no sense in testing the 'pReadBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. streamfilter.cxx 224
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 57
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 163
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 59
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. controlqueue.cpp 104
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. readwritequeue.cpp 204
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 67
  • V668 There is no sense in testing the 'deviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 470
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'pGeolocation' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sensormanager.cpp 395
  • V668 There is no sense in testing the 'm_pDataBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 531
  • V668 There is no sense in testing the 'pWriteBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 646
  • V668 There is no sense in testing the 'pReadBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 646
  • V668 There is no sense in testing the 'pBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 792
  • V668 There is no sense in testing the 'pBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 899
  • V668 There is no sense in testing the 'pBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 981
  • V668 There is no sense in testing the 'pWriteBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 1073
  • V668 There is no sense in testing the 'pWriteBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 1243
  • V668 There is no sense in testing the 'pBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. accelerometerdevice.cpp 2009
  • V668 There is no sense in testing the 'myDevice' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 60
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 155
  • V668 There is no sense in testing the 'myDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'myRemoteTarget' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. remotetarget.cpp 72
  • V668 There is no sense in testing the 'pMyDevice' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.h 47
  • V668 There is no sense in testing the 'pMyQueue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.h 46
  • V668 There is no sense in testing the 'deviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 174
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 61
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 158
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the '_pSensorManagerEvents' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sampleradiomanager.cpp 39
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 59
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 165
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 59
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 108
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 1358
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 61
  • V668 There is no sense in testing the 'devInstId' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 547
  • V668 There is no sense in testing the 'pdoName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 622
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 158
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'pMyQueue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 85
  • V668 There is no sense in testing the 'buffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ringbuffer.cpp 43
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 65
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'vDevice' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. umdf_vdev_device.cpp 69
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. umdf_vdev_dll.cpp 181
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. umdf_vdev_driver.cpp 67
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. umdf_vdev_parallelqueue.cpp 124
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. umdf_vdev_sequentialqueue.cpp 111
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 69
  • V668 There is no sense in testing the 'deviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 315
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. controlqueue.cpp 104
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 69
  • V668 There is no sense in testing the 'deviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 338
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. controlqueue.cpp 104
  • V668 There is no sense in testing the 'queue' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. readwritequeue.cpp 204
  • V668 There is no sense in testing the 'device' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 69
  • V668 There is no sense in testing the 'deviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 352
  • V668 There is no sense in testing the 'factory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllsup.cpp 183
  • V668 There is no sense in testing the 'driver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 54
  • V668 There is no sense in testing the 'pTargetBitmap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. imagefilter.cpp 209
  • V668 There is no sense in testing the 'pWiaItemWrapper' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. imagefilter.cpp 1482
  • V668 There is no sense in testing the 'pIWiaItemWrapper' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. imagefilter.cpp 1968
  • V668 There is no sense in testing the 'm_pCurrentStream' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. imagefilter.cpp 2049
  • V668 There is no sense in testing the 'pImageFilter' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. imagefilter.cpp 2181
  • V668 There is no sense in testing the 'pIWiaItemWrapper' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. segmentation.cpp 205
  • V668 There is no sense in testing the 'pSegFilter' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. segmentation.cpp 429
  • V668 There is no sense in testing the 'pResult' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. basicstr.h 963
  • V668 There is no sense in testing the 'pTmpArray' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. basicarray.h 139
  • V668 There is no sense in testing the 'pTmpArray' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. basicarray.h 186
  • V668 There is no sense in testing the 'm_pBitmapData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiadevice.h 65
  • V668 There is no sense in testing the 'm_pFormats' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiadriver.cpp 2425
  • V668 There is no sense in testing the 'pDev' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiadriver.cpp 2615
  • V668 There is no sense in testing the 'pcf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiadriver.cpp 2673
  • V668 There is no sense in testing the 'pInfo' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiapropertymanager.cpp 176
  • V668 There is no sense in testing the 'pguid' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wiapropertymanager.cpp 778
  • V668 There is no sense in testing the 'pTmpArray' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. basicarray.h 171
  • V668 There is no sense in testing the 'pTmpArray' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. basicarray.h 222
  • V668 There is no sense in testing the 'pImageCodecInfo' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fileconv.cpp 271
  • V668 There is no sense in testing the 'pInfo' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. propman.cpp 185
  • V668 There is no sense in testing the 'pguid' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. propman.cpp 1140
  • V668 There is no sense in testing the 'pwData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. scanjobs.cpp 1905
  • V668 There is no sense in testing the 'pWpdBaseDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 45
  • V668 There is no sense in testing the 'pClientContextMap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 209
  • V668 There is no sense in testing the 'pEnumeratorContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectenum.cpp 105
  • V668 There is no sense in testing the 'pResourceContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectresources.cpp 291
  • V668 There is no sense in testing the 'pWpdBaseDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 45
  • V668 There is no sense in testing the 'pClientContextMap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 290
  • V668 There is no sense in testing the 'pEnumeratorContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectenum.cpp 105
  • V668 There is no sense in testing the 'pResourceContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectresources.cpp 291
  • V668 There is no sense in testing the 'pWpdBaseDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 48
  • V668 There is no sense in testing the 'pClientContextMap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 211
  • V668 There is no sense in testing the 'pEnumeratorContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectenum.cpp 112
  • V668 There is no sense in testing the 'pszMsgBuf' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. debug.cpp 72
  • V668 There is no sense in testing the 'pFilter' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. clasfact.h 75
  • V668 There is no sense in testing the 'pFactory' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. clasfact.h 158
  • V668 There is no sense in testing the 'pRecvReport' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sensor.cpp 2320
  • V668 There is no sense in testing the 'pRecvReport' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sensor.cpp 2976
  • V668 There is no sense in testing the 'pSendReport' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. sensorddi.cpp 530
  • V668 There is no sense in testing the 'pWpdBaseDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 52
  • V668 There is no sense in testing the 'pVIC' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakecontactsservicecontent.cpp 436
  • V668 There is no sense in testing the 'pClientContextMap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 287
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdbasedriver.cpp 341
  • V668 There is no sense in testing the 'pEnumeratorContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectenum.cpp 122
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectpropertiesbulk.cpp 931
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectpropertiesbulk.cpp 1028
  • V668 There is no sense in testing the 'pResourceContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectresources.cpp 276
  • V668 There is no sense in testing the 'm_pTask' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdservicemethods.cpp 61
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdservicemethods.cpp 295
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 1927
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 1970
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2044
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2072
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2100
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2128
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2182
  • V668 There is no sense in testing the 'pContent' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. fakedevice.h 2211
  • V668 There is no sense in testing the 'pszDeviceName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. device.cpp 136
  • V668 There is no sense in testing the 'pWpdBaseDriver' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. driver.cpp 52
  • V668 There is no sense in testing the 'pClientContextMap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. queue.cpp 208
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdbasedriver.cpp 286
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectenum.cpp 283
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectmanagement.cpp 1026
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectpropertiesbulk.cpp 886
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectpropertiesbulk.cpp 986
  • V668 There is no sense in testing the 'pContext' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wpdobjectresources.cpp 895
  • V668 There is no sense in testing the 'm_pNUpPage' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. nupflt.cpp 428
  • V668 There is no sense in testing the 'm_pNUpProps' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. nuppage.cpp 82
  • V668 There is no sense in testing the 'm_pNUpTransform' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. nuppage.cpp 86
  • V668 There is no sense in testing the 'm_pNUpProps' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. nuppage.cpp 366
  • V668 There is no sense in testing the 'm_pNUpTransform' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. nuppage.cpp 370
  • V668 There is no sense in testing the 'm_pMultiByte' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. widetoutf8.cpp 136
  • V668 There is no sense in testing the 'pXpsProcessor' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xdstrmflt.cpp 127
  • V668 There is no sense in testing the 'pBuff' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xdstrmflt.cpp 157
  • V668 There is no sense in testing the 'szFileName' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xpsarch.cpp 80
  • V668 There is no sense in testing the 'pXpsWriteFile' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xpsproc.cpp 876
  • V668 There is no sense in testing the 'pBuff' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. cmimg.cpp 364
  • V668 There is no sense in testing the 'pBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. cmimg.cpp 640
  • V668 There is no sense in testing the 'pProfileData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. profile.cpp 156
  • V668 There is no sense in testing the 'm_phProfiles' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. transform.cpp 189
  • V668 There is no sense in testing the 'm_pcstrProfileKeys' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. transform.cpp 519
  • V668 There is no sense in testing the 'm_pScanBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wictobmscn.cpp 708
  • V668 There is no sense in testing the 'pFontData' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmfont.cpp 159
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. colppg.cpp 62
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. colppg.cpp 70
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. colppg.cpp 79
  • V668 There is no sense in testing the 'pXDSmplUICF' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. dllentry.cpp 154
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 62
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 70
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 79
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 83
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 93
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 97
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 107
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 111
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 121
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 125
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 135
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 144
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 153
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 162
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 171
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 180
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. ftrppg.cpp 189
  • V668 There is no sense in testing the 'lpBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. uictrl.cpp 1851
  • V668 There is no sense in testing the 'lpBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. uictrl.cpp 1960
  • V668 There is no sense in testing the 'lpOrgBuffer' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. uictrl.cpp 1970
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 63
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 71
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 80
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 89
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 93
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 103
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 107
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 117
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 121
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 131
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 135
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 145
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 149
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 159
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 163
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 173
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 177
  • V668 There is no sense in testing the 'pControl' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. wmppg.cpp 187
  • V668 There is no sense in testing the 'pXDSmplUI' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xdsmplcf.cpp 82
  • V668 There is no sense in testing the 'pXDSmplPT' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xdsmplcf.cpp 113
  • V668 There is no sense in testing the 'm_pUIProperties' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xdsmplui.cpp 477

Плохой макрос

#define MP_FREE_MEMORY(_Memory)  \
  MpFreeMemory(_Memory); _Memory = NULL;

NDIS_STATUS StaStartScan(....)
{
  ....
  if (pExternalScanRequest != NULL)
    MP_FREE_MEMORY(pExternalScanRequest);
  ....    
}

V640 The code's operational logic does not correspond with its formatting. The second statement will always be executed. It is possible that curly brackets are missing. st_scan.c 564

Макрос MP_FREE_MEMORY написан плохо. Вызовы функций не объединены в блок с помощью фигурных скобок. Конкретно здесь ошибки не будет. Просто указатель обнулится в любом случае, независимо был он равен нулю или нет.

В switch что-то не так

CPSUICALLBACK TVTestCallBack(....)
{
  ....
  switch (DMPubID)
  {
    ....
    case DMPUB_TVOPT_OVERLAY_NO:
      Action = CPSUICB_ACTION_REINIT_ITEMS;
    case DMPUB_TVOPT_ECB_EP:
      ....
      Action = CPSUICB_ACTION_OPTIF_CHANGED;
      //
      // Fall through
      //
    ....
  }
  ....
}

V519 The 'Action' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1110, 1124. cpsuidat.c 1124

Здесь что-то не так. Присваивание "Action = CPSUICB_ACTION_REINIT_ITEMS;" не имеет смысла. Ниже переменной 'Action' будет присвоено другое значение. Возможно, здесь забыт оператор 'break'. В других местах, где 'break' не нужен, написан комментарий "// Fall through". Здесь этого комментария нет.

Не ошибки, но код, который запутывает

Встречается код, который не содержит ошибок, но приводит в недоумение. Раз этот код сбил меня с толку, он будет сбивать и других программистов. Приведу одну из таких ситуаций:

BOOLEAN FillDeviceInfo(IN  PHID_DEVICE HidDevice)
{
  ....
  HidDevice->InputReportBuffer = (PCHAR)calloc(....);
  HidDevice->InputButtonCaps = buttonCaps =
   (PHIDP_BUTTON_CAPS) calloc(....);
  
  ....
  if (NULL == buttonCaps)
  {
    free(HidDevice->InputReportBuffer);
    HidDevice->InputReportBuffer = NULL;
    free(buttonCaps);
    HidDevice->InputButtonCaps = NULL;
    return (FALSE);
  }
  ....
}

V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 406

Указатель 'buttonCaps' равен NULL. Не смотря на это, выполняется бессмысленный вызов функции free(buttonCaps). Такой код заставляет подумать, что здесь есть ошибка. А её нет. Просто лишнее действие. Пустая трата времени на изучение кода. Точно такие же бессмысленные вызовы функции free() есть и в других местах:

  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 420
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 501
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 592
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 602
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 654
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 745
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 759
  • V575 The null pointer is passed into 'free' function. Inspect the first argument. pnp.c 816

Были и другие странные места в коде. Приводить их не буду. И так эта заметка подтянулась. Пора заканчивать.

Заключение

В связи с тем, что PVS-Studio находит всё больше и больше ошибок, мои статьи о проверке проектов становятся всё длиннее и длиннее. Видимо, в дальнейшем придётся описывать в статье только самое интересное и давать ссылку на файл, куда я буду выписывать подозрительные места.

Надеюсь, Microsoft правильно отнесется к моей статье. Я не хотел показать, что код плох. Статья только показывает, что ошибки есть в любых проектах, и некоторые из них мы умеем находить. Собственно, каждая моя заметка рассказывает об ошибках в каком-то из проектов. Надеюсь, статья поможет исправить некоторые недочеты. Это сэкономит время других разработчиков. А главное, не будет сомнений в репутации компании Microsoft. Согласитесь, странно слышать на конференциях о том, как Microsoft заботится о качестве, а потом найти в опубликованном коде "ASSERT (0 < dwMaskSize <5);". Качество демонстрационных программ должно быть не ниже, чем основного кода. Это тот код, по которому программисты будут судить о качестве других решений.

Популярные статьи по теме


Комментарии (0)

Следующие комментарии next comments
close comment form
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам