Системное программирование в среде 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. В программу всегда включается файл 
2. Все объекты Windows идентифицируются переменными типа Handle, причем для большинства объектов можно использовать одну и ту же общую функцию CloseHandle.
3. Рекомендуется закрывать все ранее открытые дескрипторы, если в необходимость в них отпала, чтобы освободить ресурсы. В то же время, при завершении процессов относящиеся к ним дескрипторы автоматически закрываются ОС, и если не остается ни одного дескриптора, ссылающегося на какой-либо объект, то ОС уничтожает этот объект и освобождает соответствующие ресурсы. (Примечание. Как правило, файлы подобным способом не уничтожаются.)
4. Windows определяет многочисленные символические константы и флаги. Обычно они имеют длинные имена, нередко поясняющие назначение данного объекта. В качестве типичного примера можно привести имена INVALID_HANDLE_VALUE и GENERIC_READ.
5. Функции ReadFile и WriteFile возвращают булевские значения, а не количества обработанных байтов, для передачи которых используются аргументы функций. Это определенным образом изменяет логику организации работы циклов.[11] Нулевое значение счетчика байтов указывает на попытку чтения метки конца файла и не считается ошибкой.
6. Функция GetLastError позволяет получать в любой точке программы коды системных ошибок, представляемые значениями типа DWORD. В программе 1.2 показано, как организовать вывод генерируемых Windows текстовых сообщений об ошибках.