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.

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