// Программа из конспекта "Системное программное обеспечение" // Именованные каналы в Windows // стр. ?? // Приложение SERVER_NP (системная служба) // Демонстрация использования именованных каналов // для передачи данных между процессами и службами #include #include #include #include // for SetSecurityInfo extern int addLogMessage(const char* text); int ServiceStart(); void ServiceStop(); // Идентификатор канала Pipe HANDLE hNamedPipe; // Флаг успешного создания канала BOOL fConnected; // Имя создаваемого канала Pipe LPSTR lpszPipeName = "\\\\.\\Pipe\\$MyPipe$"; int Server() { // Буфер для передачи данных через канал char szBuf[512]; // Количество байт данных, принятых через канал DWORD cbRead; // Количество байт данных, переданных через канал DWORD cbWritten; DWORD total = 0; // буфер для сообщения об ошибке, результата char message[80] = { 0 }; // Дескриптор файла FILE *hdl; addLogMessage("Named pipe server\n"); //while (true) m1: { fConnected = ConnectNamedPipe(hNamedPipe, NULL); // создаем объекты в ServiceStart() if (!fConnected) { switch (GetLastError()) { case ERROR_NO_DATA: sprintf(message, "ConnectNamedPipe: ERROR_NO_DATA"); addLogMessage(message); //CloseHandle(hNamedPipe); //return -2; break; case ERROR_PIPE_CONNECTED: sprintf(message, "ConnectNamedPipe: ERROR_PIPE_CONNECTED"); addLogMessage(message); //CloseHandle(hNamedPipe); //return -3; break; case ERROR_PIPE_LISTENING: sprintf(message, "ConnectNamedPipe: ERROR_PIPE_LISTENING"); addLogMessage(message); //CloseHandle(hNamedPipe); //return -4; break; case ERROR_CALL_NOT_IMPLEMENTED: sprintf(message, "ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED"); addLogMessage(message); //CloseHandle(hNamedPipe); //return -5; break; default: sprintf(message, "ConnectNamedPipe: Error %ld\n", GetLastError()); addLogMessage(message); //CloseHandle(hNamedPipe); //return -6; break; } sprintf(message, "Error connecting Named Pipe!\n"); addLogMessage(message); goto m1; //ServiceStop(); } } // Выводим сообщение об успешном создании канала addLogMessage("Connected. Waiting for command.\n"); // Цикл получения команд через канал while (TRUE) { // Очищаем буфер //ZeroMemory(szBuf, sizeof(szBuf)); total = 0; // Получаем очередную команду через канал Pipe if (ReadFile(hNamedPipe, szBuf, 512, &cbRead, NULL)) { // Выводим принятую команду на консоль sprintf(message,"Received: %s\n", szBuf); addLogMessage(message); // Если пришла команда "exit", завершаем работу приложения if (!strcmp(szBuf, "exit")) { WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1, &cbWritten, NULL); //break; sprintf(message, "Client exited\n"); addLogMessage(message); //continue; ServiceStop(); ServiceStart(); goto m1; } // Иначе считаем что принято имя файла else { if (hdl = fopen(szBuf, "rt")){ // цикл чтения до конца файла while (!feof(hdl)) { // чтение одного символа из файла if ((char)fgetc(hdl) == 0x20) total++; } // сообщение в консоль ошибок sprintf(message, "(Server): file:%s, spaces = %d", szBuf, total);/*\n*/ addLogMessage(message); // сообщение в канал //sprintf(message, "%d", total); WriteFile(hNamedPipe, message, strlen(message) + 1, &cbWritten, NULL); // закрытие файла fclose(hdl); } else { // сообщение в канал sprintf(message, "(Server)Can't open %s!", szBuf); addLogMessage(message); WriteFile(hNamedPipe, message, strlen(message) + 1, &cbWritten, NULL); } } } else { sprintf(message,"ReadFile: Error %ld\n", GetLastError()); //addLogMessage(message); //break; } } //CloseHandle(hNamedPipe); return 0; } int ServiceStart() { char message[80] = { 0 }; DWORD res; PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE); SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; // Создаем канал Pipe, имеющий имя lpszPipeName hNamedPipe = CreateNamedPipe( lpszPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 512, 512, 5000, &sa); //, NULL // Если возникла ошибка, выводим ее код и зваершаем работу приложения if (hNamedPipe == INVALID_HANDLE_VALUE) { sprintf(message, "CreateNamedPipe: Error %ld\n", GetLastError()); addLogMessage(message); return -1; } //SetSecurityInfo(hNamedPipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL); // Выводим сообщение о начале процесса создания канала sprintf(message, "Waiting for connect...\n"); addLogMessage(message); // Ожидаем соединения со стороны клиента //fConnected = ConnectNamedPipe(hNamedPipe, NULL); // При возникновении ошибки выводим ее код /* if (!fConnected) { switch (GetLastError()) { case ERROR_NO_DATA: sprintf(message, "ConnectNamedPipe: ERROR_NO_DATA"); addLogMessage(message); CloseHandle(hNamedPipe); return -2; //break; case ERROR_PIPE_CONNECTED: sprintf(message,"ConnectNamedPipe: ERROR_PIPE_CONNECTED"); addLogMessage(message); CloseHandle(hNamedPipe); return -3; //break; case ERROR_PIPE_LISTENING: sprintf(message, "ConnectNamedPipe: ERROR_PIPE_LISTENING"); addLogMessage(message); CloseHandle(hNamedPipe); return -4; //break; case ERROR_CALL_NOT_IMPLEMENTED: sprintf(message,"ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED"); addLogMessage(message); CloseHandle(hNamedPipe); return -5; //break; default: sprintf(message, "ConnectNamedPipe: Error %ld\n",GetLastError()); addLogMessage(message); CloseHandle(hNamedPipe); return -6; //break; } */ //CloseHandle(hNamedPipe); return 0;// -7; //} } void ServiceStop() { CloseHandle(hNamedPipe); addLogMessage("Named Pipe closed!"); }