Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1237 lines
41 KiB

  1. //--------------------------------------------------------------------
  2. // Copyright (c)1998 Microsoft Corporation, All Rights Reserved.
  3. //
  4. // bftp.cpp
  5. //
  6. // Author
  7. //
  8. // Edward Reus (EdwardR) 02-26-98 Initial Coding.
  9. //
  10. //--------------------------------------------------------------------
  11. #include "precomp.h"
  12. #include <stdlib.h>
  13. extern HINSTANCE g_hInst; // Instance of ircamera.dll
  14. static BFTP_ATTRIBUTE_MAP_ENTRY Attributes[] = {
  15. //Attr Name Type
  16. { FIL0, "FIL0", ATTR_TYPE_CHAR }, // ASCII 8.3 File Name.
  17. { LFL0, "LFL0", ATTR_TYPE_CHAR }, // SJIS or ISO8859-1 Long File Name.
  18. { TIM0, "TIM0", ATTR_TYPE_TIME }, // File create/modify time.
  19. { TYP0, "TYP0", ATTR_TYPE_BINARY }, // File or Thumbnail Information.
  20. { TMB0, "TMB0", ATTR_TYPE_BINARY }, // The scaled down image.
  21. { BDY0, "BDY0", ATTR_TYPE_BINARY }, // (?).
  22. { CMD0, "CMD0", ATTR_TYPE_BINARY }, // Command Name (?).
  23. { WHT0, "WHT0", ATTR_TYPE_CHAR }, // Category Data.
  24. { ERR0, "ERR0", ATTR_TYPE_BINARY }, // Error code.
  25. { RPL0, "RPL0", ATTR_TYPE_CHAR }, // Result: Stored File Name.
  26. { INVALID_ATTR, 0, 0 }
  27. };
  28. //
  29. // This is the bFTP for an RIMG query by the camera:
  30. //
  31. #define BFTP_RIMG_ATTR_VALUE_SIZE 14
  32. #define BFTP_RIMG_RESP_SIZE 12 + BFTP_RIMG_ATTR_VALUE_SIZE
  33. static UCHAR BftpRimgRespAttrValue[BFTP_RIMG_ATTR_VALUE_SIZE] =
  34. {
  35. 0x00, 0xff, 0xff, // Pixel aspect ratio (any).
  36. 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, // Accept image size (any).
  37. 0x05, 0xff, 0xff, 0xff, 0xff // Accept file size (any).
  38. };
  39. //
  40. // This is the bFTP for an RINF query by the camera:
  41. //
  42. #define BFTP_RINF_ATTR_VALUE_SIZE 3
  43. #define BFTP_RINF_RESP_SIZE 12 + BFTP_RINF_ATTR_VALUE_SIZE
  44. static UCHAR BftpRinfRespAttrValue[BFTP_RINF_ATTR_VALUE_SIZE] =
  45. {
  46. 0x10, 0xff, 0xff // Memory available (lots).
  47. };
  48. //
  49. // This is the bFTP for an RCMD query by the camera:
  50. //
  51. #define BFTP_RCMD_ATTR_VALUE_SIZE 5
  52. #define BFTP_RCMD_RESP_SIZE 12 + BFTP_RCMD_ATTR_VALUE_SIZE
  53. static UCHAR BftpRcmdRespAttrValue[BFTP_RCMD_ATTR_VALUE_SIZE] =
  54. {
  55. 0x20, 0x00, 0xff, 0x00, 0x01 // Accept up to 255 puts/connect.
  56. };
  57. //
  58. // Map bFTP error codes:
  59. static DWORD dwBftpErrorCodeMap[][2] =
  60. {
  61. { ERROR_PUT_UNDEFINED_ERROR, ERROR_BFTP_INVALID_PROTOCOL },
  62. { ERROR_PUT_ILLEGAL_DATA, ERROR_BFTP_INVALID_PROTOCOL },
  63. { ERROR_PUT_UNSUPPORTED_PID, ERROR_BFTP_INVALID_PROTOCOL },
  64. { ERROR_PUT_ILLEGAL_ATTRIBUTE, ERROR_BFTP_INVALID_PROTOCOL },
  65. { ERROR_PUT_UNSUPPORTED_CMD, ERROR_BFTP_INVALID_PROTOCOL },
  66. { ERROR_PUT_FILE_SYSTEM_FULL, ERROR_IRTRANP_DISK_FULL },
  67. { ERROR_PUT_NO_FILE_OR_DIR, ERROR_BFTP_INVALID_PROTOCOL },
  68. { ERROR_PUT_LOW_BATTERY, ERROR_BFTP_INVALID_PROTOCOL },
  69. { ERROR_PUT_ABORT_EXECUTION, ERROR_SCEP_ABORT },
  70. { ERROR_PUT_NO_ERROR, NO_ERROR }
  71. };
  72. //--------------------------------------------------------------------
  73. // CharToValue()
  74. //
  75. // Used in parsing the bFTP date string. In this case the maximum
  76. // value to parse is the year (YYYY).
  77. //--------------------------------------------------------------------
  78. static WORD CharToValue( IN UCHAR *pValue,
  79. IN DWORD dwLength )
  80. {
  81. #define MAX_VALUE_STR_LEN 4
  82. WORD wValue = 0;
  83. CHAR szTemp[MAX_VALUE_STR_LEN];
  84. if (dwLength < MAX_VALUE_STR_LEN)
  85. {
  86. memcpy(szTemp,pValue,dwLength);
  87. szTemp[dwLength] = 0;
  88. wValue = (WORD)atoi(szTemp);
  89. }
  90. return wValue;
  91. }
  92. //--------------------------------------------------------------------
  93. // MapBftpErrorCode()
  94. //
  95. //--------------------------------------------------------------------
  96. DWORD MapBftpErrorCode( IN DWORD dwBftpErrorCode )
  97. {
  98. DWORD dwErrorCode = NO_ERROR;
  99. DWORD dwNumCodes = sizeof(dwBftpErrorCodeMap)/(2*sizeof(DWORD));
  100. for (DWORD i=0; i<dwNumCodes; i++)
  101. {
  102. if (dwBftpErrorCode == dwBftpErrorCodeMap[i][0])
  103. {
  104. dwErrorCode = dwBftpErrorCodeMap[i][1];
  105. break;
  106. }
  107. }
  108. return dwErrorCode;
  109. }
  110. //--------------------------------------------------------------------
  111. // CSCEP_CONNECTION::ParseBftpAttributeName()
  112. //
  113. //--------------------------------------------------------------------
  114. BFTP_ATTRIBUTE *CSCEP_CONNECTION::ParseBftpAttributeName(
  115. IN BFTP_ATTRIBUTE *pAttr,
  116. IN OUT DWORD *pdwSize,
  117. OUT DWORD *pdwWhichAttr )
  118. {
  119. BFTP_ATTRIBUTE_MAP_ENTRY *pAttrMapEntry = Attributes;
  120. *pdwWhichAttr = INVALID_ATTR;
  121. while (pAttrMapEntry->pName)
  122. {
  123. if (Match4(pAttr->Name,pAttrMapEntry->pName))
  124. {
  125. *pdwWhichAttr = pAttrMapEntry->dwWhichAttr;
  126. break;
  127. }
  128. pAttrMapEntry++;
  129. }
  130. // Note: that the Length paramter is 8 bytes in from the start
  131. // of pAttr, hence the extra 8 (bytes) below:
  132. *pdwSize = *pdwSize - 8UL - pAttr->Length;
  133. pAttr = (BFTP_ATTRIBUTE*)( 8UL + pAttr->Length + (UCHAR*)pAttr );
  134. return pAttr;
  135. }
  136. //--------------------------------------------------------------------
  137. // CSCEP_CONNECTION::SaveBftpCreateDate()
  138. //
  139. // The bFTP create date/time is a character array of the form:
  140. // YYYYMMDDHHMMSS (not zero terminated).
  141. //
  142. // If it was specifed then we want to use it as the create date
  143. // of the picture file that we save the JPEG to.
  144. //--------------------------------------------------------------------
  145. DWORD CSCEP_CONNECTION::SaveBftpCreateDate( IN UCHAR *pDate,
  146. IN DWORD dwDateLength )
  147. {
  148. DWORD dwStatus = NO_ERROR;
  149. SYSTEMTIME SystemTime;
  150. FILETIME LocalTime;
  151. FILETIME FileTime;
  152. memset(&SystemTime,0,sizeof(SystemTime));
  153. if (dwDateLength == BFTP_DATE_TIME_SIZE)
  154. {
  155. //
  156. // Note that system time is in UTC, we will need to convert
  157. // this to local time...
  158. //
  159. SystemTime.wYear = CharToValue( pDate, 4 );
  160. SystemTime.wMonth = CharToValue( &(pDate[4]), 2 );
  161. SystemTime.wDay = CharToValue( &(pDate[6]), 2 );
  162. SystemTime.wHour = CharToValue( &(pDate[8]), 2 );
  163. SystemTime.wMinute = CharToValue( &(pDate[10]), 2 );
  164. SystemTime.wSecond = CharToValue( &(pDate[12]), 2 );
  165. if (SystemTimeToFileTime(&SystemTime,&LocalTime))
  166. {
  167. //
  168. // Before we use the time zone, we need to convert it to
  169. // UTC (its currently in "local time". Note that:
  170. //
  171. if (LocalFileTimeToFileTime(&LocalTime,&FileTime))
  172. {
  173. m_CreateTime = FileTime;
  174. }
  175. else
  176. {
  177. WIAS_ERROR((g_hInst,"IrTranP: SaveBftpCreateDate(): LocalFileTimeToFileTime() Failed: %d",GetLastError()));
  178. }
  179. }
  180. else
  181. {
  182. dwStatus = GetLastError();
  183. WIAS_ERROR((g_hInst,"IrTranP: SaveBftpCreateDate(): SystemTimeToFileTime(): Failed: %d", dwStatus));
  184. dwStatus = NO_ERROR;
  185. }
  186. }
  187. return dwStatus;
  188. }
  189. //--------------------------------------------------------------------
  190. // CSCEP_CONNECTION::ParseBftp()
  191. //
  192. //--------------------------------------------------------------------
  193. DWORD CSCEP_CONNECTION::ParseBftp( IN UCHAR *pBftpData,
  194. IN DWORD dwBftpDataSize,
  195. IN BOOL fSaveAsUPF,
  196. OUT DWORD *pdwBftpOp,
  197. OUT UCHAR **ppPutData,
  198. OUT DWORD *pdwPutDataSize )
  199. {
  200. DWORD i;
  201. DWORD dwStatus = NO_ERROR;
  202. DWORD dwAttrSize;
  203. DWORD dwWhichAttr;
  204. DWORD dwLength;
  205. DWORD dwSaveLength;
  206. USHORT usNumAttr;
  207. char *pszTemp;
  208. BFTP_ATTRIBUTE *pAttr;
  209. BFTP_ATTRIBUTE *pNextAttr;
  210. *pdwBftpOp = 0;
  211. *ppPutData = 0;
  212. *pdwPutDataSize = 0;
  213. #ifdef LITTLE_ENDIAN
  214. usNumAttr = ByteSwapShort( *((USHORT*)pBftpData) );
  215. #endif
  216. pAttr = (BFTP_ATTRIBUTE*)(pBftpData + sizeof(USHORT));
  217. dwAttrSize = dwBftpDataSize - sizeof(USHORT);
  218. for (i=0; i<usNumAttr; i++)
  219. {
  220. #ifdef LITTLE_ENDIAN
  221. pAttr->Length = ByteSwapLong( pAttr->Length );
  222. #endif
  223. pNextAttr = ParseBftpAttributeName( pAttr,
  224. &dwAttrSize,
  225. &dwWhichAttr );
  226. if (dwWhichAttr == INVALID_ATTR)
  227. {
  228. return ERROR_BFTP_INVALID_PROTOCOL;
  229. }
  230. if (dwWhichAttr == CMD0)
  231. {
  232. if (pAttr->Length == 2+sizeof(DWORD))
  233. {
  234. #ifdef LITTLE_ENDIAN
  235. *((DWORD*)(pAttr->Value)) = ByteSwapLong( *((DWORD*)(pAttr->Value)) );
  236. #endif
  237. }
  238. // Expect Value == 0x00010040 for a Query "WHT0" Request.
  239. // Value == 0x00000000 for a Put Request.
  240. if ( *((DWORD*)(pAttr->Value)) == 0x00010040 )
  241. {
  242. *pdwBftpOp = BFTP_QUERY_RIMG;
  243. }
  244. else if ( *((DWORD*)(pAttr->Value)) == 0 )
  245. {
  246. *pdwBftpOp = BFTP_PUT;
  247. }
  248. else
  249. {
  250. *pdwBftpOp = BFTP_UNKNOWN;
  251. }
  252. }
  253. else if (dwWhichAttr == WHT0)
  254. {
  255. if (Match4("RIMG",pAttr->Value))
  256. {
  257. dwWhichAttr = RIMG;
  258. *pdwBftpOp = BFTP_QUERY_RIMG;
  259. }
  260. else if (Match4("RINF",pAttr->Value))
  261. {
  262. dwWhichAttr = RINF;
  263. *pdwBftpOp = BFTP_QUERY_RINF;
  264. }
  265. else if (Match4("RCMD",pAttr->Value))
  266. {
  267. dwWhichAttr = RCMD;
  268. *pdwBftpOp = BFTP_QUERY_RCMD;
  269. }
  270. else
  271. {
  272. dwWhichAttr = INVALID_ATTR;
  273. *pdwBftpOp = BFTP_UNKNOWN;
  274. return ERROR_BFTP_INVALID_PROTOCOL;
  275. }
  276. }
  277. //
  278. // Short (8.3) file name:
  279. //
  280. else if (dwWhichAttr == FIL0)
  281. {
  282. // Note: That the specification limits the file
  283. // name to 8.3...
  284. dwLength = BftpValueLength(pAttr->Length);
  285. if (dwLength > FILE_NAME_SIZE)
  286. {
  287. dwLength = FILE_NAME_SIZE;
  288. }
  289. if (m_pszFileName)
  290. {
  291. FreeMemory(m_pszFileName);
  292. }
  293. m_pszFileName = (CHAR*)AllocateMemory(1+dwLength);
  294. if (!m_pszFileName)
  295. {
  296. return ERROR_OUTOFMEMORY;
  297. }
  298. memcpy(m_pszFileName,pAttr->Value,dwLength);
  299. m_pszFileName[dwLength] = 0;
  300. //
  301. // Create the name that the file will actually be saved as:
  302. //
  303. if (m_pszSaveFileName)
  304. {
  305. FreeMemory(m_pszSaveFileName);
  306. }
  307. dwSaveLength = sizeof(CHAR)*(1+dwLength) + sizeof(SZ_JPEG);
  308. m_pszSaveFileName = (CHAR*)AllocateMemory(dwSaveLength);
  309. if (!m_pszSaveFileName)
  310. {
  311. return ERROR_OUTOFMEMORY;
  312. }
  313. strcpy(m_pszSaveFileName,m_pszFileName);
  314. // File name is currently XXXXXX.UPF. Change to
  315. // XXXXXX.JPG or XXXXXX.UPF as appropriate:
  316. CHAR *psz = strrchr(m_pszSaveFileName,PERIOD);
  317. if (psz)
  318. {
  319. *psz = 0; // Remove old suffix.
  320. }
  321. if (fSaveAsUPF)
  322. {
  323. strcat(m_pszSaveFileName,SZ_UPF); // UPF file.
  324. }
  325. else
  326. {
  327. strcat(m_pszSaveFileName,SZ_JPEG); // JPG file.
  328. }
  329. }
  330. //
  331. // UPF body: headers + thumbnail + jpeg image ...
  332. //
  333. else if (dwWhichAttr == BDY0)
  334. {
  335. // This is a PUT.
  336. ASSERT(*pdwBftpOp == BFTP_PUT);
  337. *ppPutData = pAttr->Value;
  338. *pdwPutDataSize = dwBftpDataSize - (DWORD)(pAttr->Value - pBftpData);
  339. }
  340. //
  341. // Long file name:
  342. //
  343. else if (dwWhichAttr == LFL0)
  344. {
  345. if (m_pszLongFileName)
  346. {
  347. FreeMemory(m_pszLongFileName);
  348. }
  349. dwLength = BftpValueLength(pAttr->Length);
  350. m_pszLongFileName = (CHAR*)AllocateMemory(1+dwLength);
  351. if (!m_pszLongFileName)
  352. {
  353. return ERROR_OUTOFMEMORY;
  354. }
  355. memcpy(m_pszLongFileName,pAttr->Value,dwLength);
  356. m_pszLongFileName[dwLength] = 0;
  357. CHAR *pszLongFileName = strrchr(m_pszLongFileName,'\\');
  358. if (pszLongFileName)
  359. {
  360. pszLongFileName++; // Skip over the file separator...
  361. }
  362. else
  363. {
  364. pszLongFileName = m_pszLongFileName;
  365. }
  366. dwLength = strlen(pszLongFileName);
  367. if (m_pszSaveFileName)
  368. {
  369. FreeMemory(m_pszSaveFileName);
  370. }
  371. dwSaveLength = sizeof(CHAR)*(1+dwLength) + sizeof(SZ_JPEG);
  372. m_pszSaveFileName = (CHAR*)AllocateMemory(dwSaveLength);
  373. if (!m_pszSaveFileName)
  374. {
  375. return ERROR_OUTOFMEMORY;
  376. }
  377. // File name is now XXXXXX.JPG. Change to
  378. // XXXXXX.JPEG or XXXXXX.UPF as appropriate:
  379. CHAR *psz = strrchr(m_pszSaveFileName,PERIOD);
  380. if (psz)
  381. {
  382. *psz = 0;
  383. }
  384. if (fSaveAsUPF)
  385. {
  386. strcat(m_pszSaveFileName,SZ_UPF);
  387. }
  388. else
  389. {
  390. strcat(m_pszSaveFileName,SZ_JPEG);
  391. }
  392. #ifdef DBG_IO
  393. WIAS_TRACE((g_hInst,"CSCEP_CONNECTION::ParseBftp(): File: %s", m_pszSaveFileName));
  394. #endif
  395. }
  396. //
  397. // Create Date/Time:
  398. //
  399. else if (dwWhichAttr == TIM0)
  400. {
  401. dwLength = BftpValueLength(pAttr->Length);
  402. SaveBftpCreateDate(pAttr->Value,dwLength);
  403. #ifdef DBG_DATE
  404. pszTemp = (char*)AllocateMemory(1+dwLength);
  405. if (pszTemp)
  406. {
  407. memcpy(pszTemp,pAttr->Value,dwLength);
  408. pszTemp[dwLength] = 0;
  409. FreeMemory(pszTemp);
  410. }
  411. #endif
  412. }
  413. //
  414. // Camera sent back a bFTP error code:
  415. //
  416. else if (dwWhichAttr == ERR0)
  417. {
  418. *pdwBftpOp = BFTP_ERROR;
  419. *ppPutData = pAttr->Value;
  420. *pdwPutDataSize = BftpValueLength(pAttr->Length);
  421. dwStatus = ByteSwapShort( *((USHORT*)(pAttr->Value)) );
  422. }
  423. // BUGBUG: May need to byte swap other attributes as well when
  424. // the protocol is extended...
  425. pAttr = pNextAttr;
  426. }
  427. return dwStatus;
  428. }
  429. //--------------------------------------------------------------------
  430. // CSCEP_CONNECTION::ParseUpfHeaders()
  431. //
  432. //--------------------------------------------------------------------
  433. DWORD CSCEP_CONNECTION::ParseUpfHeaders( IN UCHAR *pPutData,
  434. IN DWORD dwPutDataSize,
  435. OUT DWORD *pdwJpegOffset,
  436. OUT DWORD *pdwJpegSize )
  437. {
  438. DWORD dwStatus = NO_ERROR;
  439. DWORD dwStartAddress;
  440. DWORD dwDataSize;
  441. INT iGmtOffset = 0;
  442. WORD wYear;
  443. WORD wMonth;
  444. WORD wDay;
  445. SYSTEMTIME SystemTime;
  446. FILETIME LocalTime;
  447. FILETIME FileTime;
  448. UPF_HEADER *pUpfHeader;
  449. UPF_ENTRY *pUpfEntry1;
  450. UPF_ENTRY *pUpfEntry2;
  451. PICTURE_INFORMATION_DATA *pThumbnailInfo = 0;
  452. PICTURE_INFORMATION_DATA *pPictureInfo = 0;
  453. ASSERT(dwPutDataSize >= UPF_TOTAL_HEADER_SIZE);
  454. if (!pPutData)
  455. {
  456. *pdwJpegOffset = 0;
  457. *pdwJpegSize = 0;
  458. return ERROR_BFTP_INVALID_PROTOCOL;
  459. }
  460. pUpfHeader = (UPF_HEADER*)pPutData;
  461. pUpfEntry1 = (UPF_ENTRY*)(UPF_HEADER_SIZE + (UCHAR*)pUpfHeader);
  462. pUpfEntry2 = (UPF_ENTRY*)(UPF_ENTRY_SIZE + (UCHAR*)pUpfEntry1);
  463. dwStartAddress = ByteSwapLong(pUpfEntry2->dwStartAddress);
  464. dwDataSize = ByteSwapLong(pUpfEntry2->dwDataSize);
  465. #ifdef DBG_PROPERTIES
  466. WIAS_TRACE((g_hInst,"CSCEP_CONNECTION::ParseUpfHeaders(): NumTables: %d", pUpfHeader->NumTables));
  467. pPictureInfo = (PICTURE_INFORMATION_DATA*)pUpfEntry2->InformationData;
  468. WIAS_TRACE((g_hInst,"CSCEP_CONNECTION::ParseUpfHeaders(): Rotation: %d", pPictureInfo->RotationSet));
  469. #endif
  470. *pdwJpegOffset = UPF_HEADER_SIZE + 4*UPF_ENTRY_SIZE + dwStartAddress;
  471. *pdwJpegSize = dwDataSize;
  472. #ifdef UPF_FILES
  473. *pdwJpegOffset = 0;
  474. *pdwJpegSize = 0;
  475. #endif
  476. // Ok, now parse the picture creation date/time, if one is
  477. // defined.
  478. //
  479. // Note that the date/time is local time, with a GMT offset.
  480. // Since we will use local system time conversions, we will
  481. // not need the GMT offset.
  482. if (pUpfHeader->CreateDate[UPF_GMT_OFFSET] != 0x80)
  483. {
  484. iGmtOffset = (pUpfHeader->CreateDate[UPF_GMT_OFFSET])/4;
  485. }
  486. memcpy(&wYear,&(pUpfHeader->CreateDate[UPF_YEAR]),sizeof(SHORT) );
  487. wYear = ByteSwapShort(wYear);
  488. wMonth = pUpfHeader->CreateDate[UPF_MONTH];
  489. wDay = pUpfHeader->CreateDate[UPF_DAY];
  490. // At least the Year/Month/Day must be specified, else we
  491. // won't use the date. If the Hour/Minute/Second are known,
  492. // then we will use them as well.
  493. if ((wYear != 0xffff) && (wMonth != 0xff) && (wDay != 0xff))
  494. {
  495. memset(&SystemTime,0,sizeof(SystemTime));
  496. SystemTime.wYear = wYear;
  497. SystemTime.wMonth = wMonth;
  498. SystemTime.wDay = wDay;
  499. if (pUpfHeader->CreateDate[UPF_HOUR] != 0xff)
  500. {
  501. SystemTime.wHour = pUpfHeader->CreateDate[UPF_HOUR];
  502. if (pUpfHeader->CreateDate[UPF_MINUTE] != 0xff)
  503. {
  504. SystemTime.wMinute = pUpfHeader->CreateDate[UPF_MINUTE];
  505. if (pUpfHeader->CreateDate[UPF_SECOND] != 0xff)
  506. {
  507. SystemTime.wSecond = pUpfHeader->CreateDate[UPF_SECOND];
  508. }
  509. }
  510. }
  511. if (SystemTimeToFileTime(&SystemTime,&LocalTime))
  512. {
  513. //
  514. // Before we save the date/time, we need to convert it to
  515. // UTC (its currently in "local time". Note that:
  516. //
  517. if (LocalFileTimeToFileTime(&LocalTime,&FileTime))
  518. {
  519. m_CreateTime = FileTime;
  520. }
  521. else
  522. {
  523. WIAS_ERROR((g_hInst,"IrTranP: SaveBftpCreateDate(): LocalFileTimeToFileTime() Failed: %d",GetLastError()));
  524. }
  525. }
  526. else
  527. {
  528. dwStatus = GetLastError();
  529. WIAS_ERROR((g_hInst,"IrTranP: ParseUpfHeaders(): Invalid Picture Create Date/Time. Status: %d", dwStatus));
  530. dwStatus = NO_ERROR;
  531. }
  532. }
  533. else
  534. {
  535. WIAS_TRACE((g_hInst,"IrTranP: ParseUpfHeaders(): No Picture Create Date/Time."));
  536. }
  537. return dwStatus;
  538. }
  539. //--------------------------------------------------------------------
  540. // CSCEP_CONNECTION::BuildBftpWht0RinfPdu()
  541. //
  542. //--------------------------------------------------------------------
  543. DWORD CSCEP_CONNECTION::BuildBftpWht0RinfPdu(
  544. OUT SCEP_HEADER **ppPdu,
  545. OUT DWORD *pdwPduSize,
  546. OUT SCEP_REQ_HEADER_LONG **ppCommand,
  547. OUT COMMAND_HEADER **ppCommandHeader )
  548. {
  549. DWORD dwStatus = NO_ERROR;
  550. SCEP_HEADER *pHeader;
  551. SCEP_REQ_HEADER_LONG *pCommand;
  552. COMMAND_HEADER *pCommandHeader;
  553. UCHAR *pUserData;
  554. USHORT *pwNumAttributes;
  555. BFTP_ATTRIBUTE *pAttrib;
  556. *ppPdu = 0;
  557. *pdwPduSize = 0;
  558. *ppCommand = 0;
  559. *ppCommandHeader = 0;
  560. pHeader = NewPdu(); // Size is MAX_PDU_SIZE by default...
  561. if (!pHeader)
  562. {
  563. return ERROR_OUTOFMEMORY;
  564. }
  565. memset(pHeader,0,MAX_PDU_SIZE);
  566. // This is the total size of the PDU that we will construct:
  567. DWORD dwPduSize = sizeof(SCEP_HEADER)
  568. + sizeof(SCEP_REQ_HEADER_LONG)
  569. + sizeof(USHORT) // Num Attributes
  570. + sizeof(BFTP_ATTRIBUTE)
  571. + sizeof(DWORD)
  572. + sizeof(BFTP_ATTRIBUTE)
  573. + WHT0_ATTRIB_SIZE;
  574. // Length2 is the total size of the PDU minus the offset+size
  575. // of Length2:
  576. USHORT wLength2 = (USHORT)dwPduSize - 6;
  577. pHeader->Null = 0;
  578. pHeader->MsgType = MSG_TYPE_DATA;
  579. pCommand = (SCEP_REQ_HEADER_LONG*)(pHeader->Rest);
  580. pCommand->InfType = INF_TYPE_USER_DATA;
  581. pCommand->Length1 = USE_LENGTH2; // 0xff
  582. pCommand->Length2 = wLength2;
  583. pCommand->InfVersion = INF_VERSION;
  584. pCommand->DFlag = DFLAG_SINGLE_PDU;
  585. pCommand->Length3 = pCommand->Length2 - 4; //
  586. pCommandHeader = (COMMAND_HEADER*)(pCommand->CommandHeader);
  587. pCommandHeader->Marker58h = 0x58;
  588. pCommandHeader->PduType = PDU_TYPE_REQUEST;
  589. pCommandHeader->Length4 = pCommand->Length2 - 10;
  590. pCommandHeader->DestPid = m_SrcPid;
  591. pCommandHeader->SrcPid = m_DestPid;
  592. pCommandHeader->CommandId = (USHORT)m_dwCommandId;
  593. memcpy( pCommandHeader->DestMachineId,
  594. m_pPrimaryMachineId,
  595. MACHINE_ID_SIZE );
  596. memcpy( pCommandHeader->SrcMachineId,
  597. m_pSecondaryMachineId,
  598. MACHINE_ID_SIZE );
  599. #ifdef LITTLE_ENDIAN
  600. pCommand->Length2 = ByteSwapShort(pCommand->Length2);
  601. pCommand->Length3 = ByteSwapShort(pCommand->Length3);
  602. ByteSwapCommandHeader(pCommandHeader);
  603. #endif
  604. // Setup the bFTP:
  605. pUserData = pCommand->UserData;
  606. pwNumAttributes = (USHORT*)pUserData;
  607. *pwNumAttributes = 2; // Two bFTP attributes.
  608. #ifdef LITTLE_ENDIAN
  609. *pwNumAttributes = ByteSwapShort(*pwNumAttributes);
  610. #endif
  611. pUserData += sizeof(*pwNumAttributes);
  612. // First attribute is CMD0:
  613. DWORD dwCmd0AttrValue = CMD0_ATTR_VALUE; // Fixed constant!
  614. pAttrib = (BFTP_ATTRIBUTE*)pUserData;
  615. memcpy( pAttrib->Name, Attributes[CMD0].pName, BFTP_NAME_SIZE );
  616. pAttrib->Length = sizeof(pAttrib->Type)
  617. + sizeof(pAttrib->Flag)
  618. + sizeof(dwCmd0AttrValue);
  619. pAttrib->Type = ATTR_TYPE_BINARY; // 0x00
  620. pAttrib->Flag = ATTR_FLAG_DEFAULT; // 0x00
  621. memcpy( pAttrib->Value, &dwCmd0AttrValue, sizeof(dwCmd0AttrValue) );
  622. #ifdef LITTLE_ENDIAN
  623. pAttrib->Length = ByteSwapLong(pAttrib->Length);
  624. #endif
  625. // Second attribute is WHT0:RINF
  626. pAttrib = (BFTP_ATTRIBUTE*)(pUserData
  627. + sizeof(BFTP_ATTRIBUTE)
  628. + sizeof(dwCmd0AttrValue));
  629. memcpy( pAttrib->Name, Attributes[WHT0].pName, BFTP_NAME_SIZE );
  630. pAttrib->Length = sizeof(pAttrib->Type)
  631. + sizeof(pAttrib->Flag)
  632. + WHT0_ATTRIB_SIZE;
  633. pAttrib->Type = ATTR_TYPE_CHAR; // 0x00
  634. pAttrib->Flag = ATTR_FLAG_DEFAULT; // 0x00
  635. memcpy( pAttrib->Value, SZ_RINF, WHT0_ATTRIB_SIZE );
  636. #ifdef LITTLE_ENDIAN
  637. pAttrib->Length = ByteSwapLong(pAttrib->Length);
  638. #endif
  639. // Done.
  640. *ppPdu = pHeader;
  641. *pdwPduSize = dwPduSize;
  642. *ppCommand = pCommand;
  643. *ppCommandHeader = pCommandHeader;
  644. return dwStatus;
  645. }
  646. //--------------------------------------------------------------------
  647. // CSCEP_CONNECTION::BuildBftpPutPdu()
  648. //
  649. // The PUT command will span multiple PDUs, this function builds the
  650. // Nth fragment. Note that the first will also hold the attributes
  651. // for the UPF file to be sent (in addition to the SCEP header stuff).
  652. //
  653. // Each PDU will also contain (MAX_PDU_SIZE - *pdwPduSize) bytes
  654. // of the UPF file, but that isn't added in here. You add that
  655. // yourself in the PDU starting at *ppCommand->UserData[].
  656. //
  657. // On success, return NO_ERROR, else return a non-zero error code.
  658. //
  659. // dwUpfFileSize -- The total UPF file size.
  660. //
  661. // pszUpfFile -- The 8.3 name of the UPF file.
  662. //
  663. // pdwFragNo -- The fragment number that was built, cycle this
  664. // back into each successive call to BuildBftpPutPdu().
  665. // Initialize *pdwFragNo to zero before the first
  666. // iteration, then leave it alone.
  667. //--------------------------------------------------------------------
  668. DWORD CSCEP_CONNECTION::BuildBftpPutPdu(
  669. IN DWORD dwUpfFileSize,
  670. IN CHAR *pszUpfFileName,
  671. IN OUT DWORD *pdwFragNo,
  672. OUT SCEP_HEADER **ppPdu,
  673. OUT DWORD *pdwHeaderSize,
  674. OUT SCEP_REQ_HEADER_LONG_FRAG **ppCommand )
  675. {
  676. DWORD dwStatus = NO_ERROR;
  677. SCEP_HEADER *pHeader;
  678. SCEP_REQ_HEADER_LONG_FRAG *pCommand;
  679. COMMAND_HEADER *pCommandHeader;
  680. UCHAR *pUserData;
  681. USHORT *pwNumAttributes;
  682. BFTP_ATTRIBUTE *pAttrib;
  683. DWORD dwUpfFileNameLength = strlen(pszUpfFileName);
  684. *ppPdu = 0;
  685. *pdwHeaderSize = 0;
  686. *ppCommand = 0;
  687. pHeader = NewPdu(); // Size is MAX_PDU_SIZE by default...
  688. if (!pHeader)
  689. {
  690. return ERROR_OUTOFMEMORY;
  691. }
  692. memset(pHeader,0,MAX_PDU_SIZE);
  693. // This is the size of the SCEP (and bFTP) headers part of the
  694. // PDU that we will construct. dwHeaderSize1 is the header size for
  695. // the first PDU, dwHeaderSizeN is the header size for the rest of
  696. // the PDUs. Note that the Nth (N>1) header does not include the
  697. // COMMAN_HEADER (28 bytes).
  698. DWORD dwHeaderSize;
  699. DWORD dwHeaderSize1 = sizeof(SCEP_HEADER)
  700. + sizeof(SCEP_REQ_HEADER_LONG_FRAG)
  701. + sizeof(USHORT) // Num Attributes
  702. + sizeof(BFTP_ATTRIBUTE) // For CMD0
  703. + sizeof(DWORD)
  704. + sizeof(BFTP_ATTRIBUTE) // For FIL0
  705. + dwUpfFileNameLength
  706. + sizeof(BFTP_ATTRIBUTE); // For BDY0
  707. DWORD dwHeaderSizeN = sizeof(SCEP_HEADER)
  708. + FIELD_OFFSET(SCEP_REQ_HEADER_LONG_FRAG,CommandHeader);
  709. DWORD dwSpace1; // Space left after the header in PDU #1.
  710. DWORD dwSpaceN; // Space left after the header in the Nth PDU.
  711. DWORD dwFileSizeLeft; // File Size minus what will fit in the
  712. // first PDU.
  713. DWORD dwNumFullPdus; // Number of "full" PDUs after PDU #1.
  714. DWORD dwLastPdu; // = 1 iff the last PDU is partially full.
  715. DWORD dwNumPdus; // Total number of fragments to hold the file.
  716. // Figure out which fragment we are on:
  717. if (*pdwFragNo == 0)
  718. {
  719. dwHeaderSize = dwHeaderSize1;
  720. m_Fragmented = TRUE;
  721. m_DFlag = DFLAG_FIRST_FRAGMENT;
  722. // The space in the PDU left after the first and Nth headers:
  723. dwSpace1 = MAX_PDU_SIZE - dwHeaderSize1;
  724. dwSpaceN = MAX_PDU_SIZE - dwHeaderSizeN;
  725. // The number of full PDUs following the first PDU:
  726. dwFileSizeLeft = dwUpfFileSize - dwSpace1;
  727. dwNumFullPdus = dwFileSizeLeft / dwSpaceN;
  728. // See if there is a trailer PDU with remaining data:
  729. dwLastPdu = ((dwFileSizeLeft % dwSpaceN) > 0)? 1 : 0;
  730. dwNumPdus = 1 + dwNumFullPdus + dwLastPdu;
  731. *pdwFragNo = 1;
  732. m_dwSequenceNo = 0; // First Seq.No. is 0.
  733. m_dwRestNo = dwNumPdus; // Rest starts at Total Num. Fragments.
  734. }
  735. else
  736. {
  737. dwHeaderSize = dwHeaderSizeN;
  738. *pdwFragNo++;
  739. m_dwSequenceNo++;
  740. m_dwRestNo--;
  741. if (m_dwRestNo == 0)
  742. {
  743. return ERROR_BFTP_NO_MORE_FRAGMENTS; // Called to many times...
  744. }
  745. else if (m_dwRestNo == 1)
  746. {
  747. m_DFlag = DFLAG_LAST_FRAGMENT;
  748. }
  749. else
  750. {
  751. m_DFlag = DFLAG_FRAGMENT;
  752. }
  753. }
  754. // Length2 is the total size of the PDU minus the offset+size
  755. // of Length2:
  756. USHORT wLength2 = (USHORT)(MAX_PDU_SIZE - 6);
  757. DWORD dwLength4 = dwUpfFileSize + 22 + 48;
  758. DWORD dwBdy0Length = dwUpfFileSize + 2;
  759. pHeader->Null = 0;
  760. pHeader->MsgType = MSG_TYPE_DATA;
  761. pCommand = (SCEP_REQ_HEADER_LONG_FRAG*)(pHeader->Rest);
  762. pCommand->InfType = INF_TYPE_USER_DATA;
  763. pCommand->Length1 = USE_LENGTH2; // 0xff
  764. pCommand->Length2 = wLength2;
  765. pCommand->InfVersion = INF_VERSION;
  766. pCommand->DFlag = m_DFlag;
  767. pCommand->Length3 = pCommand->Length2 - 12; //
  768. pCommand->SequenceNo = m_dwSequenceNo;
  769. pCommand->RestNo = m_dwRestNo;
  770. #ifdef LITTLE_ENDIAN
  771. pCommand->Length2 = ByteSwapShort(pCommand->Length2);
  772. pCommand->Length3 = ByteSwapShort(pCommand->Length3);
  773. pCommand->SequenceNo = ByteSwapLong(pCommand->SequenceNo);
  774. pCommand->RestNo = ByteSwapLong(pCommand->RestNo);
  775. #endif
  776. // Note that there is a COMMAND_HEADER in the SCEP header only
  777. // for the first fragment.
  778. if (m_DFlag == DFLAG_FIRST_FRAGMENT)
  779. {
  780. pCommandHeader = (COMMAND_HEADER*)(pCommand->CommandHeader);
  781. pCommandHeader->Marker58h = 0x58;
  782. pCommandHeader->PduType = PDU_TYPE_REQUEST;
  783. pCommandHeader->Length4 = dwLength4;
  784. pCommandHeader->DestPid = m_SrcPid;
  785. pCommandHeader->SrcPid = m_DestPid;
  786. pCommandHeader->CommandId = (USHORT)m_dwCommandId;
  787. memcpy( pCommandHeader->DestMachineId,
  788. m_pPrimaryMachineId,
  789. MACHINE_ID_SIZE );
  790. memcpy( pCommandHeader->SrcMachineId,
  791. m_pSecondaryMachineId,
  792. MACHINE_ID_SIZE );
  793. #ifdef LITTLE_ENDIAN
  794. ByteSwapCommandHeader(pCommandHeader);
  795. #endif
  796. // Setup the bFTP:
  797. pUserData = pCommand->UserData;
  798. pwNumAttributes = (USHORT*)pUserData;
  799. *pwNumAttributes = 3; // Three bFTP attributes.
  800. #ifdef LITTLE_ENDIAN
  801. *pwNumAttributes = ByteSwapShort(*pwNumAttributes);
  802. #endif
  803. pUserData += sizeof(*pwNumAttributes);
  804. // First attribute is CMD0:
  805. DWORD dwCmd0AttrValue = 0x00000000;
  806. pAttrib = (BFTP_ATTRIBUTE*)pUserData;
  807. memcpy( pAttrib->Name, Attributes[CMD0].pName, BFTP_NAME_SIZE );
  808. pAttrib->Length = sizeof(pAttrib->Type)
  809. + sizeof(pAttrib->Flag)
  810. + sizeof(ULONG);
  811. pAttrib->Type = ATTR_TYPE_BINARY; // 0x00
  812. pAttrib->Flag = ATTR_FLAG_DEFAULT; // 0x00
  813. memcpy( pAttrib->Value, &dwCmd0AttrValue, sizeof(dwCmd0AttrValue) );
  814. #ifdef LITTLE_ENDIAN
  815. pAttrib->Length = ByteSwapLong(pAttrib->Length);
  816. #endif
  817. // Second attribute is FIL0 (with the 8.3 UPF file name):
  818. pAttrib = (BFTP_ATTRIBUTE*)(pUserData
  819. + sizeof(BFTP_ATTRIBUTE)
  820. + sizeof(dwCmd0AttrValue));
  821. memcpy( pAttrib->Name, Attributes[FIL0].pName, BFTP_NAME_SIZE );
  822. pAttrib->Length = sizeof(pAttrib->Type)
  823. + sizeof(pAttrib->Flag)
  824. + dwUpfFileNameLength;
  825. pAttrib->Type = ATTR_TYPE_CHAR; // 0x01
  826. pAttrib->Flag = ATTR_FLAG_DEFAULT; // 0x00
  827. memcpy( pAttrib->Value, pszUpfFileName, dwUpfFileNameLength );
  828. #ifdef LITTLE_ENDIAN
  829. pAttrib->Length = ByteSwapLong(pAttrib->Length);
  830. #endif
  831. // Third attribute is BDY0 (with the value being the whole UPF file):
  832. pAttrib = (BFTP_ATTRIBUTE*)( (char*)pAttrib
  833. + sizeof(BFTP_ATTRIBUTE)
  834. + dwUpfFileNameLength );
  835. memcpy( pAttrib->Name, Attributes[BDY0].pName, BFTP_NAME_SIZE );
  836. pAttrib->Length = dwBdy0Length;
  837. pAttrib->Type = ATTR_TYPE_BINARY; // 0x00
  838. pAttrib->Flag = ATTR_FLAG_DEFAULT; // 0x00
  839. // pAttrib->Value is not copied in (its the entire UPF file).
  840. #ifdef LITTLE_ENDIAN
  841. pAttrib->Length = ByteSwapLong(pAttrib->Length);
  842. #endif
  843. }
  844. // Done.
  845. *ppPdu = pHeader;
  846. *pdwHeaderSize = dwHeaderSize;
  847. *ppCommand = pCommand;
  848. return dwStatus;
  849. }
  850. //--------------------------------------------------------------------
  851. // CSCEP_CONNECTION::BuildBftpRespPdu()
  852. //
  853. //--------------------------------------------------------------------
  854. DWORD CSCEP_CONNECTION::BuildBftpRespPdu(
  855. IN DWORD dwPduSize,
  856. OUT SCEP_HEADER **ppPdu,
  857. OUT SCEP_REQ_HEADER_SHORT **ppCommand,
  858. OUT COMMAND_HEADER **ppCommandHeader )
  859. {
  860. DWORD dwStatus = NO_ERROR;
  861. SCEP_HEADER *pHeader;
  862. SCEP_REQ_HEADER_SHORT *pCommand;
  863. COMMAND_HEADER *pCommandHeader;
  864. *ppPdu = 0;
  865. *ppCommand = 0;
  866. *ppCommandHeader = 0;
  867. pHeader = NewPdu(); // BUGBUG: Use dwPduSize?
  868. if (!pHeader)
  869. {
  870. return ERROR_OUTOFMEMORY;
  871. }
  872. memset(pHeader,0,MAX_PDU_SIZE); // BUGBUG: Use dwPduSize?
  873. pHeader->Null = 0;
  874. pHeader->MsgType = MSG_TYPE_DATA;
  875. pCommand = (SCEP_REQ_HEADER_SHORT*)(pHeader->Rest);
  876. pCommand->InfType = INF_TYPE_USER_DATA;
  877. pCommand->Length1 = (UCHAR)dwPduSize - 4; // Four bytes from the start.
  878. pCommand->InfVersion = INF_VERSION;
  879. pCommand->DFlag = DFLAG_SINGLE_PDU;
  880. pCommand->Length3 = (USHORT)dwPduSize - 8; // Eight bytes from the start.
  881. #ifdef LITTLE_ENDIAN
  882. pCommand->Length3 = ByteSwapShort(pCommand->Length3);
  883. #endif
  884. pCommandHeader = (COMMAND_HEADER*)(pCommand->CommandHeader);
  885. pCommandHeader->Marker58h = 0x58;
  886. pCommandHeader->PduType = PDU_TYPE_REPLY_ACK;
  887. pCommandHeader->Length4 = dwPduSize - 14; // Twelve bytes from the start.
  888. pCommandHeader->DestPid = m_SrcPid;
  889. pCommandHeader->SrcPid = m_DestPid;
  890. pCommandHeader->CommandId = (USHORT)m_dwCommandId;
  891. memcpy( pCommandHeader->DestMachineId,
  892. m_pPrimaryMachineId,
  893. MACHINE_ID_SIZE );
  894. memcpy( pCommandHeader->SrcMachineId,
  895. m_pSecondaryMachineId,
  896. MACHINE_ID_SIZE );
  897. #ifdef LITTLE_ENDIAN
  898. ByteSwapCommandHeader(pCommandHeader);
  899. #endif
  900. *ppPdu = pHeader;
  901. *ppCommand = pCommand;
  902. *ppCommandHeader = pCommandHeader;
  903. return dwStatus;
  904. }
  905. //--------------------------------------------------------------------
  906. // CSCEP_CONNECTION::BuildWht0RespPdu()
  907. //
  908. //--------------------------------------------------------------------
  909. DWORD CSCEP_CONNECTION::BuildWht0RespPdu( IN DWORD dwWht0Type,
  910. OUT SCEP_HEADER **ppPdu,
  911. OUT DWORD *pdwPduSize )
  912. {
  913. DWORD dwStatus = NO_ERROR;
  914. DWORD dwPduSize;
  915. DWORD dwRespSize;
  916. DWORD dwAttrValueSize;
  917. SCEP_HEADER *pHeader;
  918. SCEP_REQ_HEADER_SHORT *pCommand;
  919. COMMAND_HEADER *pCommandHeader;
  920. UCHAR *pQueryResp;
  921. USHORT *pUShort;
  922. BFTP_ATTRIBUTE *pAttr;
  923. UCHAR *pAttrValue;
  924. *ppPdu = 0;
  925. *pdwPduSize = 0;
  926. if (dwWht0Type == BFTP_QUERY_RIMG)
  927. {
  928. dwRespSize = BFTP_RIMG_RESP_SIZE;
  929. dwAttrValueSize = BFTP_RIMG_ATTR_VALUE_SIZE;
  930. pAttrValue = BftpRimgRespAttrValue;
  931. }
  932. else if (dwWht0Type == BFTP_QUERY_RINF)
  933. {
  934. dwRespSize = BFTP_RINF_RESP_SIZE;
  935. dwAttrValueSize = BFTP_RINF_ATTR_VALUE_SIZE;
  936. pAttrValue = BftpRinfRespAttrValue;
  937. }
  938. else if (dwWht0Type == BFTP_QUERY_RCMD)
  939. {
  940. dwRespSize = BFTP_RCMD_RESP_SIZE;
  941. dwAttrValueSize = BFTP_RCMD_ATTR_VALUE_SIZE;
  942. pAttrValue = BftpRcmdRespAttrValue;
  943. }
  944. else
  945. {
  946. return ERROR_BFTP_INVALID_PROTOCOL;
  947. }
  948. dwPduSize = SCEP_HEADER_SIZE
  949. + SCEP_REQ_HEADER_SHORT_SIZE
  950. + dwRespSize;
  951. dwStatus = BuildBftpRespPdu( dwPduSize,
  952. &pHeader,
  953. &pCommand,
  954. &pCommandHeader );
  955. if (dwStatus == NO_ERROR)
  956. {
  957. pQueryResp = pCommand->UserData;
  958. // Set the number of bFTP attributes:
  959. pUShort = (USHORT*)pQueryResp;
  960. *pUShort = 1;
  961. #ifdef LITTLE_ENDIAN
  962. *pUShort = ByteSwapShort(*pUShort);
  963. #endif
  964. // Set the BDY0 for the query response:
  965. pAttr = (BFTP_ATTRIBUTE*)(sizeof(USHORT)+pQueryResp);
  966. memcpy(pAttr->Name,Attributes[BDY0].pName,BFTP_NAME_SIZE);
  967. pAttr->Length = 2 + dwAttrValueSize;
  968. pAttr->Type = ATTR_TYPE_BINARY;
  969. pAttr->Flag = ATTR_FLAG_DEFAULT;
  970. memcpy(pAttr->Value,pAttrValue,dwAttrValueSize);
  971. #ifdef LITTLE_ENDIAN
  972. pAttr->Length = ByteSwapLong(pAttr->Length);
  973. #endif
  974. *ppPdu = pHeader;
  975. *pdwPduSize = dwPduSize;
  976. }
  977. return dwStatus;
  978. }
  979. //--------------------------------------------------------------------
  980. // CSCEP_CONNECTION::BuildPutRespPdu()
  981. //
  982. //--------------------------------------------------------------------
  983. DWORD CSCEP_CONNECTION::BuildPutRespPdu( IN DWORD dwPduAckOrNack,
  984. IN USHORT usErrorCode,
  985. OUT SCEP_HEADER **ppPdu,
  986. OUT DWORD *pdwPduSize )
  987. {
  988. DWORD dwStatus = NO_ERROR;
  989. DWORD dwPduSize;
  990. DWORD dwRespSize;
  991. DWORD dwFileNameLen;
  992. SCEP_HEADER *pHeader;
  993. SCEP_REQ_HEADER_SHORT *pCommand;
  994. COMMAND_HEADER *pCommandHeader;
  995. UCHAR *pQueryResp;
  996. USHORT *pUShort;
  997. BFTP_ATTRIBUTE *pAttr;
  998. UCHAR *pAttrValue;
  999. *ppPdu = 0;
  1000. *pdwPduSize = 0;
  1001. if (dwPduAckOrNack == PDU_TYPE_REPLY_ACK)
  1002. {
  1003. if (!m_pszFileName)
  1004. {
  1005. return ERROR_BFTP_INVALID_PROTOCOL;
  1006. }
  1007. dwFileNameLen = strlen( (const char *)m_pszFileName );
  1008. dwRespSize = sizeof(USHORT) + sizeof(BFTP_ATTRIBUTE) + dwFileNameLen;
  1009. }
  1010. else
  1011. {
  1012. dwRespSize = sizeof(USHORT) + sizeof(BFTP_ATTRIBUTE) + sizeof(USHORT);
  1013. }
  1014. dwPduSize = SCEP_HEADER_SIZE
  1015. + SCEP_REQ_HEADER_SHORT_SIZE
  1016. + dwRespSize;
  1017. dwStatus = BuildBftpRespPdu( dwPduSize,
  1018. &pHeader,
  1019. &pCommand,
  1020. &pCommandHeader );
  1021. if (dwStatus == NO_ERROR)
  1022. {
  1023. pQueryResp = pCommand->UserData;
  1024. // Set the number of bFTP attributes:
  1025. pUShort = (USHORT*)pQueryResp;
  1026. *pUShort = 1;
  1027. #ifdef LITTLE_ENDIAN
  1028. *pUShort = ByteSwapShort(*pUShort);
  1029. #endif
  1030. pAttr = (BFTP_ATTRIBUTE*)(sizeof(USHORT)+pQueryResp);
  1031. if (dwPduAckOrNack == PDU_TYPE_REPLY_ACK)
  1032. {
  1033. // Set the RPL0 for the put response (ACK):
  1034. memcpy(pAttr->Name,Attributes[RPL0].pName,BFTP_NAME_SIZE);
  1035. pAttr->Length = 2 + dwFileNameLen;
  1036. pAttr->Type = ATTR_TYPE_CHAR;
  1037. pAttr->Flag = ATTR_FLAG_DEFAULT;
  1038. memcpy(pAttr->Value,m_pszFileName,dwFileNameLen);
  1039. }
  1040. else
  1041. {
  1042. // Nack the PUT:
  1043. pCommandHeader->PduType = PDU_TYPE_REPLY_NACK;
  1044. // Set the ERR0 for the put response (NACK):
  1045. memcpy(pAttr->Name,Attributes[RPL0].pName,BFTP_NAME_SIZE);
  1046. pAttr->Length = 2 + sizeof(USHORT);
  1047. pAttr->Type = ATTR_TYPE_BINARY;
  1048. pAttr->Flag = ATTR_FLAG_DEFAULT;
  1049. #ifdef LITTLE_ENDIAN
  1050. usErrorCode = ByteSwapShort(usErrorCode);
  1051. #endif
  1052. memcpy(pAttr->Value,&usErrorCode,sizeof(USHORT));
  1053. }
  1054. #ifdef LITTLE_ENDIAN
  1055. pAttr->Length = ByteSwapLong(pAttr->Length);
  1056. #endif
  1057. *ppPdu = pHeader;
  1058. *pdwPduSize = dwPduSize;
  1059. }
  1060. return dwStatus;
  1061. }