Source code of Windows XP (NT5)
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.

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