///////////////////////////////////////// // Dir window callback LRESULT CALLBACK ShDirProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static const int tTabs[] = { 90, 125 }; struct S_DirectoryContent *pDir = (struct S_DirectoryContent *) lParam; HWND hLBWnd = GetDlgItem (hWnd, IDC_LB_SHDIR); int Ark; switch (message) { case WM_INITDIALOG : // Set the window name to either tftpd32 or tftpd64 SetWindowText (hWnd, TFTPD_DIR_TITLE); ListBox_SetTabStops ( hLBWnd, SizeOfTab(tTabs), tTabs ); ListBox_ResetContent ( hLBWnd ); for ( Ark=0 ; Ark < pDir->nb ; Ark++ ) ListBox_AddString ( hLBWnd, pDir->ent[Ark].file_descr ); CenterChildWindow (hWnd, CCW_INSIDE | CCW_VISIBLE); // If GUI is in remote mode, deactivate Explorer Button if ( IsGuiConnectedToRemoteService () ) Button_Enable (GetDlgItem (hWnd, IDC_SD_EXPLORER), FALSE); break; case WM_COMMAND : Handle_VM_Command (hWnd, wParam, lParam); break; case WM_CLOSE : case WM_DESTROY : EndDialog (hWnd, 0); break; } // switch return FALSE; } // ShDirProc
///////////////////////////// // Fenetre Background gestion des appels TCP // LRESULT CALLBACK TftpClientProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { DWORD nbWrt; struct tftphdr *tpr, *tps; time_t dNow; int Ark; HWND hCBWnd, hParentWnd; time (&dNow); switch (message) { ///////////////////////// // Message Windows case WM_INITCLIENT : // only one client transfer available hTftpClientSemaphore = CreateSemaphore(NULL, 1, 1, TFTP_CLIENT_SEMAPHORE); hTftpClientWnd = hWnd; hParentWnd = GetParent (hWnd); EnableWindow (GetDlgItem (hParentWnd, IDC_CLIENT_BREAK_BUTTON), FALSE); SetDlgItemText (hParentWnd, IDC_CLIENT_BLOCK, ""); // populate combo with proposed block sizes hCBWnd = GetDlgItem (hParentWnd, IDC_CB_DATASEG); for (Ark=0 ; Ark<SizeOfTab (tBlkSize); Ark++) ComboBox_AddString (hCBWnd, tBlkSize[Ark].szBlkSize); ComboBox_SetCurSel (hCBWnd, 0); // uncheck "Send full path to server" SendDlgItemMessage (hParentWnd, IDC_CLIENT_FULL_PATH, BM_SETCHECK, BST_UNCHECKED, 0); // edittext IDC_CLIENT_FILE will accept dropped file (works only because it is on the top in Z-Order DragAcceptFiles (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), TRUE); // fEditBoxProc = (WNDPROC) SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWL_WNDPROC, (LONG) TftpClientFileNameProc); fEditBoxProc = (WNDPROC) SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_WNDPROC, (LONG_PTR) TftpClientFileNameProc); // SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_FILE), GWL_USERDATA, (LONG) TftpClientFileNameProc); SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_USERDATA, (LONG_PTR) TftpClientFileNameProc); break; case WM_CLOSE : LogToMonitor ("GUI: Closing Tftp Client"); CloseHandle (hTftpClientSemaphore); CloseHandle (sTC.hFile); closesocket (sTC.s); break; case WM_COMMAND : Handle_VM_Command (hWnd, wParam, lParam); break; case WM_TIMER : KillTimer(hWnd, wParam); PostMessage (hWnd, wParam, 0, (LPARAM) -1); // pour pas confondre break; ////////////////////// // Download : fichier envoyé par le serveur case WM_CLIENT_DATA : // WSAAsyncSelect (sTC.s, hWnd, 0, 0); A SUPPRIMER KillTimer(hWnd, wParam); if (sTC.bBreak) return FALSE; sTC.nRcvd = 0; // On est reveillé par un message reçu tpr = (struct tftphdr *) sTC.BufRcv; if (WSAGETSELECTEVENT(lParam) == FD_READ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); // parcours des codes retours switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount==0) TftpProcessOACK (); break; case TFTP_DATA : // a data packet has been received. Check #block if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount+1) ) { if ( !WriteFile (sTC.hFile, tpr->th_data, sTC.nRcvd - TFTP_DATA_HEADERSIZE, & nbWrt, NULL) || sTC.nRcvd-TFTP_DATA_HEADERSIZE!=nbWrt) return BadEndOfTransfer ("Error in writing file.\nError code is %d (%s)", GetLastError(), LastErrorText()); sTC.nCount++; sTC.nRetransmit = 0; // prepare Ack block tps = (struct tftphdr *) sTC.BufSnd; tps->th_opcode = htons (TFTP_ACK), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE; // compute MD5 MD5Update (& sTC.m.ctx, tpr->th_data, nbWrt); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // La comparaison marche si le paquet est le bon ou une répétition du précédent message if ( htons (tpr->th_block) == (unsigned short) sTC.nCount) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout waiting block #%d", sTC.nCount+1); send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_DATA, sTC.dwTimeout, NULL); } // sTC.nRcvd ne peut être inférieur que si on a reçu un block if ( htons (tpr->th_opcode)==TFTP_DATA && sTC.nRcvd!=0 && sTC.nRcvd < sTC.nPktSize + TFTP_DATA_HEADERSIZE) return TransferOK (dNow); Statistics (dNow); break; //////////////////////// // Upload : server sends ACK case WM_CLIENT_ACK : KillTimer(hWnd, wParam); if (sTC.bBreak || sTC.s==INVALID_SOCKET) return FALSE; // socket not closed by StopTransfer tpr = (struct tftphdr *) sTC.BufRcv; if ( WSAGETSELECTEVENT(lParam) == FD_READ ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount!=0) break; // ignore message TftpProcessOACK (); tpr->th_block = htons(0); // pour passer en dessous // Fall through case TFTP_ACK : if ( htons (tpr->th_block) == (unsigned short) sTC.nCount ) { // prepare Data block tps = (struct tftphdr *) sTC.BufSnd; if ( !ReadFile (sTC.hFile, tps->th_data, sTC.nPktSize, & sTC.nRcvd, NULL) ) { if (sTC.nToSend == TFTP_DATA_HEADERSIZE + sTC.nPktSize) // file was exactly N * PkSize return TransferOK (dNow); else return BadEndOfTransfer ("Error in reading file.\nError code is %d (%s)", GetLastError(), LastErrorText()); } if (sTC.nRcvd == 0) // EOF { if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize) return TransferOK (dNow); } sTC.nCount++; sTC.nRetransmit = 0; tps->th_opcode = htons (TFTP_DATA), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE + sTC.nRcvd; // compute MD5 MD5Update (& sTC.m.ctx, tps->th_data, sTC.nRcvd); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // Timeout or ack of previous block else if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount-1) ) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout while waiting ack block #%d", sTC.nCount); // une possibilité : on est au dernier message et le serveur TFTP n'a pas acquitté // --> on renvoie, mais sur Timeout, on signale un transfert OK if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize && sTC.nRetransmit<TFTP_RETRANSMIT) return TransferOK (dNow); } send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_ACK, sTC.dwTimeout, NULL); Statistics (dNow); break; } // switch message return DefWindowProc (hWnd, message, wParam, lParam); } // TftpProc