Системное программирование в среде Windows | страница 28




>int main (int argc, LPTSTR argv []) {

> HANDLE hIn, hOut;

> DWORD nIn, nOut;

> CHAR Buffer [BUF_SIZE];

> if (argc != 3) {

>  printf ("Использование: cpW файл1 файл2\n");

>  return 1;

> }

> hIn = CreateFile(argv [1], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

> if (hIn == INVALID_HANDLE_VALUE) {

>  printf("Невозможно открыть входной файл. Ошибка: %х\n", GetLastError());

>  return 2;

> }

> hOut = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

> if (hOut == INVALID_HANDLE_VALUE) {

>  printf("Невозможно открыть выходной файл. Ошибка: %x\n", GetLastError()); 

>  return 3;

> }

> while (ReadFile(hIn, Buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {

>  WriteFile(hOut, Buffer, nIn, &nOut, NULL);

>  if (nIn != nOut) {

>   printf ("Неустранимая ошибка записи: %x\n", GetLastError());

>   return 4;

>  }

> }

> CloseHandle(hIn);

> CloseHandle(hOut);

> return 0;

>}

Этот простой пример иллюстрирует некоторые особенности программирования в среде Windows, к подробному рассмотрению которых мы приступим в главе 2.

1. В программу всегда включается файл , в котором содержатся все необходимые определения функций и типов данных Windows.[10]

2. Все объекты Windows идентифицируются переменными типа Handle, причем для большинства объектов можно использовать одну и ту же общую функцию CloseHandle.

3. Рекомендуется закрывать все ранее открытые дескрипторы, если в необходимость в них отпала, чтобы освободить ресурсы. В то же время, при завершении процессов относящиеся к ним дескрипторы автоматически закрываются ОС, и если не остается ни одного дескриптора, ссылающегося на какой-либо объект, то ОС уничтожает этот объект и освобождает соответствующие ресурсы. (Примечание. Как правило, файлы подобным способом не уничтожаются.)

4. Windows определяет многочисленные символические константы и флаги. Обычно они имеют длинные имена, нередко поясняющие назначение данного объекта. В качестве типичного примера можно привести имена INVALID_HANDLE_VALUE и GENERIC_READ.

5. Функции ReadFile и WriteFile возвращают булевские значения, а не количества обработанных байтов, для передачи которых используются аргументы функций. Это определенным образом изменяет логику организации работы циклов.[11] Нулевое значение счетчика байтов указывает на попытку чтения метки конца файла и не считается ошибкой.

6. Функция GetLastError позволяет получать в любой точке программы коды системных ошибок, представляемые значениями типа DWORD. В программе 1.2 показано, как организовать вывод генерируемых Windows текстовых сообщений об ошибках.