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.

1236 lines
29 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: buffer.c
  7. //
  8. // Description: This module contains routines to manipulate cached
  9. // information. ie volume info, server properties and
  10. // ETC mappings info.
  11. //
  12. // History:
  13. // May 11,1992. NarenG Created original version.
  14. //
  15. #include "afpsvcp.h"
  16. // This should be more than the size (in bytes) all the value names
  17. // each AfpMultSzInfo structure. It will be used to calculate the amount
  18. // of memory needed to create a multi-sz.
  19. //
  20. #define AFP_CUMULATIVE_VALNAME_SIZE 150
  21. // This data structure will be used by AfpBufParseMultiSz and
  22. // AfpBufMakeMultiSz.
  23. //
  24. typedef struct _AfpMultiSzInfo {
  25. DWORD dwType; // Type of data, string or DWORD
  26. DWORD dwOffset; // Offset of this field from the start
  27. LPWSTR lpwsValueName; // Value name for this field.
  28. // If this is NULL then it does not
  29. // have a value name. It is the
  30. // value name for this MULT_SZ.
  31. DWORD fIsInPlace; // If string, is it a pointer or a
  32. // buffer.
  33. DWORD cch; // If fIsInPlace is TRUE, then how
  34. // big (in UNICODE chars.) is the
  35. // buffer.
  36. } AFP_MULTISZ_INFO, *PAFP_MULTISZ_INFO;
  37. static AFP_MULTISZ_INFO AfpVolumeMultiSz[] = {
  38. REG_SZ,
  39. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_name ),
  40. NULL,
  41. FALSE,
  42. 0,
  43. REG_SZ,
  44. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_password ),
  45. AFPREG_VALNAME_PASSWORD,
  46. FALSE,
  47. 0,
  48. REG_DWORD,
  49. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_max_uses ),
  50. AFPREG_VALNAME_MAXUSES,
  51. FALSE,
  52. 0,
  53. REG_DWORD,
  54. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_props_mask ),
  55. AFPREG_VALNAME_PROPS,
  56. FALSE,
  57. 0,
  58. REG_SZ,
  59. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_path ),
  60. AFPREG_VALNAME_PATH,
  61. FALSE,
  62. 0,
  63. REG_NONE, 0, 0, 0, 0
  64. };
  65. static AFP_MULTISZ_INFO AfpExtensionMultiSz[] = {
  66. REG_SZ,
  67. AFP_FIELD_OFFSET( AFP_EXTENSION, afpe_extension[0] ),
  68. NULL,
  69. TRUE,
  70. AFP_FIELD_SIZE( AFP_EXTENSION, afpe_extension ),
  71. REG_DWORD,
  72. AFP_FIELD_OFFSET( AFP_EXTENSION, afpe_tcid ),
  73. AFPREG_VALNAME_ID,
  74. FALSE,
  75. 0,
  76. REG_NONE, 0, 0, 0, 0
  77. };
  78. static AFP_MULTISZ_INFO AfpTypeCreatorMultiSz[] = {
  79. REG_SZ,
  80. AFP_FIELD_OFFSET(AFP_TYPE_CREATOR, afptc_creator[0] ),
  81. AFPREG_VALNAME_CREATOR,
  82. TRUE,
  83. AFP_FIELD_SIZE(AFP_TYPE_CREATOR, afptc_creator ),
  84. REG_SZ,
  85. AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_type[0] ),
  86. AFPREG_VALNAME_TYPE,
  87. TRUE,
  88. AFP_FIELD_SIZE( AFP_TYPE_CREATOR, afptc_type ),
  89. REG_SZ,
  90. AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_comment[0] ),
  91. AFPREG_VALNAME_COMMENT,
  92. TRUE,
  93. AFP_FIELD_SIZE( AFP_TYPE_CREATOR, afptc_comment ),
  94. REG_DWORD,
  95. AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_id ),
  96. NULL,
  97. FALSE,
  98. 0,
  99. REG_NONE, 0, 0, 0, 0
  100. };
  101. static AFP_MULTISZ_INFO AfpIconMultiSz[] = {
  102. REG_SZ,
  103. AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_type[0] ),
  104. AFPREG_VALNAME_TYPE,
  105. TRUE,
  106. AFP_FIELD_SIZE( AFP_ICON_INFO, afpicon_type ),
  107. REG_SZ,
  108. AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_creator[0] ),
  109. AFPREG_VALNAME_CREATOR,
  110. TRUE,
  111. AFP_FIELD_SIZE( AFP_ICON_INFO, afpicon_creator ),
  112. REG_DWORD,
  113. AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_icontype ),
  114. AFPREG_VALNAME_ICONTYPE,
  115. FALSE,
  116. 0,
  117. REG_DWORD,
  118. AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_length ),
  119. AFPREG_VALNAME_LENGTH,
  120. FALSE,
  121. 0,
  122. REG_SZ,
  123. AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_data ),
  124. AFPREG_VALNAME_DATA,
  125. FALSE,
  126. 0,
  127. REG_NONE, 0, 0, 0, 0
  128. };
  129. // These arrays represents the byte offsets, from the beginning of the
  130. // structure, of the LPWSTR fields.
  131. //
  132. static BYTE ServerOffsetTable[] = {
  133. AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_name ),
  134. AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_login_msg ),
  135. AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_codepage ),
  136. 0xFF
  137. };
  138. static BYTE VolumeOffsetTable[] = {
  139. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_name ),
  140. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_password ),
  141. AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_path ),
  142. 0xFF
  143. };
  144. static BYTE DirOffsetTable[] = {
  145. AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_path ),
  146. AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_owner ),
  147. AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_group ),
  148. 0xFF
  149. };
  150. static BYTE SessionOffsetTable[] = {
  151. AFP_FIELD_OFFSET( AFP_SESSION_INFO, afpsess_ws_name ),
  152. AFP_FIELD_OFFSET( AFP_SESSION_INFO, afpsess_username ),
  153. 0xFF
  154. };
  155. static BYTE FileOffsetTable[] = {
  156. AFP_FIELD_OFFSET( AFP_FILE_INFO, afpfile_path ),
  157. AFP_FIELD_OFFSET( AFP_FILE_INFO, afpfile_username ),
  158. 0xFF
  159. };
  160. static BYTE ConnectionOffsetTable[] = {
  161. AFP_FIELD_OFFSET( AFP_CONNECTION_INFO, afpconn_username ),
  162. AFP_FIELD_OFFSET( AFP_CONNECTION_INFO, afpconn_volumename ),
  163. 0xFF
  164. };
  165. static BYTE MessageOffsetTable[] = {
  166. AFP_FIELD_OFFSET( AFP_MESSAGE_INFO, afpmsg_text ),
  167. 0xFF
  168. };
  169. static BYTE FinderOffsetTable[] = {
  170. AFP_FIELD_OFFSET( AFP_FINDER_INFO, afpfd_path ),
  171. 0xFF
  172. };
  173. //**
  174. //
  175. // Call: AfpBufStructureSize
  176. //
  177. // Returns: The size (in bytes) of the data withing the structure.
  178. //
  179. // Description: It will calculate the size of all the variable data and
  180. // add that to the fixed size of the structure.
  181. //
  182. DWORD
  183. AfpBufStructureSize(
  184. IN AFP_STRUCTURE_TYPE dwStructureType,
  185. IN LPBYTE lpbStructure
  186. )
  187. {
  188. DWORD cbStructureSize;
  189. DWORD dwIndex;
  190. DWORD cbBufSize;
  191. LPWSTR* plpwsStringField;
  192. PBYTE OffsetTable;
  193. switch( dwStructureType ) {
  194. case AFP_VOLUME_STRUCT:
  195. OffsetTable = VolumeOffsetTable;
  196. cbStructureSize = sizeof( AFP_VOLUME_INFO );
  197. break;
  198. case AFP_SERVER_STRUCT:
  199. OffsetTable = ServerOffsetTable;
  200. cbStructureSize = sizeof( AFP_SERVER_INFO );
  201. break;
  202. case AFP_DIRECTORY_STRUCT:
  203. OffsetTable = DirOffsetTable;
  204. cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
  205. break;
  206. case AFP_EXTENSION_STRUCT:
  207. return( sizeof(AFP_EXTENSION) );
  208. break;
  209. case AFP_TYPECREATOR_STRUCT:
  210. return( sizeof(AFP_TYPE_CREATOR) );
  211. break;
  212. case AFP_MESSAGE_STRUCT:
  213. OffsetTable = MessageOffsetTable;
  214. cbStructureSize = sizeof( AFP_MESSAGE_INFO );
  215. break;
  216. case AFP_ICON_STRUCT:
  217. return( sizeof(AFP_ICON_INFO) +
  218. ((PAFP_ICON_INFO)lpbStructure)->afpicon_length );
  219. break;
  220. case AFP_FINDER_STRUCT:
  221. OffsetTable = FinderOffsetTable;
  222. cbStructureSize = sizeof( AFP_FINDER_INFO );
  223. break;
  224. default:
  225. return( 0 );
  226. }
  227. // First calculate the amount of memory that will be needed to
  228. // store all the string information.
  229. //
  230. for( dwIndex = 0, cbBufSize = 0;
  231. OffsetTable[dwIndex] != 0xFF;
  232. dwIndex++
  233. ) {
  234. plpwsStringField=(LPWSTR*)((ULONG_PTR)lpbStructure + OffsetTable[dwIndex]);
  235. cbBufSize += ( ( *plpwsStringField == NULL ) ? 0 :
  236. STRLEN( *plpwsStringField ) + 1 );
  237. }
  238. // Convert to UNICODE size
  239. //
  240. cbBufSize *= sizeof( WCHAR );
  241. // Add size of fixed part of the structure
  242. //
  243. cbBufSize += cbStructureSize;
  244. return( cbBufSize );
  245. }
  246. //**
  247. //
  248. // Call: AfpBufMakeFSDRequest
  249. //
  250. // Returns: NO_ERROR
  251. // ERROR_NOT_ENOUGH_MEMORY
  252. //
  253. // Description: This routine is called by the worker routines for the client
  254. // API calls. The purpose of this routine is to convert a
  255. // AFP_XXX_INFO structure passed by the client API into a
  256. // contiguous self-relative buffer. This has to be done because
  257. // the FSD cannot reference pointers to user space.
  258. //
  259. // This routine will allocate the required amount of memory to
  260. // store all the information in self relative form. It is
  261. // the reponsibility of the caller to free this memory.
  262. //
  263. // All pointer fields will be converted to offsets from the
  264. // beginning of the structure.
  265. //
  266. // The cbReqPktSize parameter specifies how many bytes of space
  267. // should be allocated before the self relative data structure.
  268. // i.e.
  269. // |------------|
  270. // |cbReqPktSize|
  271. // | bytes |
  272. // |------------|
  273. // | Self |
  274. // | relative |
  275. // | structure |
  276. // |------------|
  277. //
  278. DWORD
  279. AfpBufMakeFSDRequest(
  280. // Buffer as received by the client API
  281. //
  282. IN LPBYTE pBuffer,
  283. // Size of FSD request packet.
  284. //
  285. IN DWORD cbReqPktSize,
  286. IN AFP_STRUCTURE_TYPE dwStructureType,
  287. // Self-relative form of I/P buf
  288. //
  289. OUT LPBYTE *ppSelfRelativeBuf,
  290. // Size of self relative buf
  291. //
  292. OUT LPDWORD lpdwSelfRelativeBufSize
  293. )
  294. {
  295. LPBYTE lpbSelfRelBuf;
  296. DWORD cbSRBufSize;
  297. DWORD dwIndex;
  298. LPWSTR lpwsVariableData;
  299. LPWSTR * plpwsStringField;
  300. LPWSTR * plpwsStringFieldSR;
  301. PBYTE OffsetTable;
  302. DWORD cbStructureSize;
  303. // Initialize the offset table and the structure size values
  304. //
  305. switch( dwStructureType ) {
  306. case AFP_VOLUME_STRUCT:
  307. OffsetTable = VolumeOffsetTable;
  308. cbStructureSize = sizeof( AFP_VOLUME_INFO );
  309. break;
  310. case AFP_SERVER_STRUCT:
  311. OffsetTable = ServerOffsetTable;
  312. cbStructureSize = sizeof( AFP_SERVER_INFO );
  313. break;
  314. case AFP_DIRECTORY_STRUCT:
  315. OffsetTable = DirOffsetTable;
  316. cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
  317. break;
  318. case AFP_MESSAGE_STRUCT:
  319. OffsetTable = MessageOffsetTable;
  320. cbStructureSize = sizeof( AFP_MESSAGE_INFO );
  321. break;
  322. case AFP_FINDER_STRUCT:
  323. OffsetTable = FinderOffsetTable;
  324. cbStructureSize = sizeof( AFP_FINDER_INFO );
  325. break;
  326. default:
  327. return( ERROR_INVALID_PARAMETER );
  328. }
  329. cbSRBufSize = cbReqPktSize + AfpBufStructureSize(dwStructureType, pBuffer);
  330. // Allocate space for self relative buffer
  331. //
  332. if ( ( lpbSelfRelBuf = (LPBYTE)LocalAlloc( LPTR, cbSRBufSize ) ) == NULL )
  333. return( ERROR_NOT_ENOUGH_MEMORY );
  334. *ppSelfRelativeBuf = lpbSelfRelBuf;
  335. *lpdwSelfRelativeBufSize = cbSRBufSize;
  336. // Advance this pointer beyond the request packet
  337. //
  338. lpbSelfRelBuf += cbReqPktSize;
  339. // memcpy to fill in the non-string data
  340. //
  341. CopyMemory( lpbSelfRelBuf, pBuffer, cbStructureSize );
  342. // Now copy all the strings
  343. //
  344. for( dwIndex = 0,
  345. lpwsVariableData = (LPWSTR)((ULONG_PTR)lpbSelfRelBuf + cbStructureSize);
  346. OffsetTable[dwIndex] != 0xFF;
  347. dwIndex++ ) {
  348. // This will point to a string pointer field in the non self-relative
  349. // structure.
  350. //
  351. plpwsStringField = (LPWSTR*)((ULONG_PTR)pBuffer + OffsetTable[dwIndex]);
  352. // This will point to the corresponding string pointer field in the
  353. // self-relative structure
  354. //
  355. plpwsStringFieldSR=(LPWSTR*)((ULONG_PTR)lpbSelfRelBuf+OffsetTable[dwIndex]);
  356. // If there is no string to be copied, then just set to NULL
  357. //
  358. if ( *plpwsStringField == NULL )
  359. *plpwsStringFieldSR = NULL;
  360. else {
  361. // There is a string so copy it
  362. //
  363. STRCPY( lpwsVariableData, *plpwsStringField );
  364. // Store the pointer value
  365. //
  366. *plpwsStringFieldSR = lpwsVariableData;
  367. // Convert the pointer to this data to an offset
  368. //
  369. POINTER_TO_OFFSET( *plpwsStringFieldSR, lpbSelfRelBuf );
  370. // Update the pointer to where the next variable length data
  371. // will be stored.
  372. //
  373. lpwsVariableData += ( STRLEN( *plpwsStringField ) + 1 );
  374. }
  375. }
  376. return( NO_ERROR );
  377. }
  378. //**
  379. //
  380. // Call: AfpBufOffsetToPointer
  381. //
  382. // Returns: none.
  383. //
  384. // Description: Will walk a list of structures, converting all offsets
  385. // within each structure to pointers.
  386. //
  387. VOID
  388. AfpBufOffsetToPointer(
  389. IN OUT LPBYTE pBuffer,
  390. IN DWORD dwNumEntries,
  391. IN AFP_STRUCTURE_TYPE dwStructureType
  392. )
  393. {
  394. PBYTE OffsetTable;
  395. DWORD cbStructureSize;
  396. LPWSTR *plpwsStringField;
  397. DWORD dwIndex;
  398. // Initialize the offset table and the structure size values
  399. //
  400. switch( dwStructureType ) {
  401. case AFP_VOLUME_STRUCT:
  402. OffsetTable = VolumeOffsetTable;
  403. cbStructureSize = sizeof( AFP_VOLUME_INFO );
  404. break;
  405. case AFP_SESSION_STRUCT:
  406. OffsetTable = SessionOffsetTable;
  407. cbStructureSize = sizeof( AFP_SESSION_INFO );
  408. break;
  409. case AFP_CONNECTION_STRUCT:
  410. OffsetTable = ConnectionOffsetTable;
  411. cbStructureSize = sizeof( AFP_CONNECTION_INFO );
  412. break;
  413. case AFP_FILE_STRUCT:
  414. OffsetTable = FileOffsetTable;
  415. cbStructureSize = sizeof( AFP_FILE_INFO );
  416. break;
  417. case AFP_DIRECTORY_STRUCT:
  418. OffsetTable = DirOffsetTable;
  419. cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
  420. break;
  421. case AFP_MESSAGE_STRUCT:
  422. OffsetTable = MessageOffsetTable;
  423. cbStructureSize = sizeof( AFP_MESSAGE_INFO );
  424. break;
  425. case AFP_SERVER_STRUCT:
  426. OffsetTable = ServerOffsetTable;
  427. cbStructureSize = sizeof( AFP_SERVER_INFO );
  428. break;
  429. default:
  430. return;
  431. }
  432. // Walk the list and convert each structure.
  433. //
  434. while( dwNumEntries-- ) {
  435. // Convert every LPWSTR from an offset to a pointer
  436. //
  437. for( dwIndex = 0; OffsetTable[dwIndex] != 0xFF; dwIndex++ ) {
  438. plpwsStringField = (LPWSTR*)( (ULONG_PTR)pBuffer
  439. + (DWORD)OffsetTable[dwIndex] );
  440. OFFSET_TO_POINTER( *plpwsStringField, pBuffer );
  441. }
  442. pBuffer += cbStructureSize;
  443. }
  444. return;
  445. }
  446. //**
  447. //
  448. // Call: AfpBufMakeMultiSz
  449. //
  450. // Returns: NO_ERROR - success
  451. // ERROR_NOT_ENOUGH_MEMORY
  452. //
  453. // Description: This routine will take a give structure and create a
  454. // REG_MULTI_SZ from it. This can then be set directly into the
  455. // registry. It is the caller's responsibility to free
  456. // the memory allocated for *ppbMultiSz.
  457. //
  458. DWORD
  459. AfpBufMakeMultiSz(
  460. IN AFP_STRUCTURE_TYPE dwStructureType,
  461. IN LPBYTE lpbStructure,
  462. OUT LPBYTE * ppbMultiSz,
  463. OUT LPDWORD lpdwMultiSzSize
  464. )
  465. {
  466. PAFP_MULTISZ_INFO pAfpMultiSz;
  467. PWCHAR lpwchWalker;
  468. PVOID pData;
  469. DWORD dwIndex;
  470. DWORD cbStructureSize;
  471. switch( dwStructureType ) {
  472. case AFP_VOLUME_STRUCT:
  473. pAfpMultiSz = AfpVolumeMultiSz;
  474. break;
  475. case AFP_EXTENSION_STRUCT:
  476. pAfpMultiSz = AfpExtensionMultiSz;
  477. break;
  478. case AFP_TYPECREATOR_STRUCT:
  479. pAfpMultiSz = AfpTypeCreatorMultiSz;
  480. break;
  481. case AFP_ICON_STRUCT:
  482. pAfpMultiSz = AfpIconMultiSz;
  483. break;
  484. default:
  485. return( ERROR_INVALID_PARAMETER );
  486. }
  487. // Allocate enough memory to create the multi-sz.
  488. // AFP_CUMULATIVE_VALNAME_SIZE should be greater than the sum of all the
  489. // value names of all the structures.
  490. //
  491. cbStructureSize = AfpBufStructureSize( dwStructureType, lpbStructure )
  492. + AFP_CUMULATIVE_VALNAME_SIZE;
  493. if ( ( *ppbMultiSz = (LPBYTE)LocalAlloc( LPTR, cbStructureSize ) ) == NULL )
  494. return( ERROR_NOT_ENOUGH_MEMORY );
  495. ZeroMemory( *ppbMultiSz, cbStructureSize );
  496. // For every field, we create a string
  497. //
  498. for ( dwIndex = 0,
  499. lpwchWalker = (PWCHAR)*ppbMultiSz;
  500. pAfpMultiSz[dwIndex].dwType != REG_NONE;
  501. dwIndex++
  502. ){
  503. // This is the value name so do not put it in the buffer.
  504. //
  505. if ( pAfpMultiSz[dwIndex].lpwsValueName == NULL )
  506. continue;
  507. STRCPY( lpwchWalker, pAfpMultiSz[dwIndex].lpwsValueName );
  508. STRCAT( lpwchWalker, TEXT("="));
  509. lpwchWalker += STRLEN( lpwchWalker );
  510. pData = lpbStructure + pAfpMultiSz[dwIndex].dwOffset;
  511. // Convert to string and concatenate
  512. //
  513. if ( pAfpMultiSz[dwIndex].dwType == REG_DWORD ) {
  514. UCHAR chAnsiBuf[12];
  515. _itoa( *((LPDWORD)pData), chAnsiBuf, 10 );
  516. mbstowcs( lpwchWalker, chAnsiBuf, sizeof(chAnsiBuf) );
  517. }
  518. if ( pAfpMultiSz[dwIndex].dwType == REG_SZ ) {
  519. // Check if this is a pointer or an in-place buffer
  520. //
  521. if ( pAfpMultiSz[dwIndex].fIsInPlace )
  522. STRCPY( lpwchWalker, (LPWSTR)pData );
  523. else {
  524. if ( *(LPWSTR*)pData != NULL )
  525. STRCPY( lpwchWalker, *((LPWSTR*)pData) );
  526. }
  527. }
  528. lpwchWalker += ( STRLEN( lpwchWalker ) + 1 );
  529. }
  530. *lpdwMultiSzSize = (DWORD)((ULONG_PTR)lpwchWalker - (ULONG_PTR)(*ppbMultiSz) ) + sizeof(WCHAR);
  531. return( NO_ERROR );
  532. }
  533. //**
  534. //
  535. // Call: AfpBufParseMultiSz
  536. //
  537. // Returns: NO_ERROR - success
  538. // ERROR_INVALID_PARAMETER
  539. //
  540. // Description: This routine will parse a REG_MULTI_SZ and fill in the
  541. // appropriate data structure. All pointers will point to
  542. // the pbMultiSz input parameter.
  543. //
  544. DWORD
  545. AfpBufParseMultiSz(
  546. IN AFP_STRUCTURE_TYPE dwStructureType,
  547. IN LPBYTE pbMultiSz,
  548. OUT LPBYTE pbStructure
  549. )
  550. {
  551. PAFP_MULTISZ_INFO pAfpMultiSz;
  552. DWORD dwIndex;
  553. DWORD cbStructSize;
  554. LPWSTR lpwchWalker;
  555. PVOID pData;
  556. UCHAR chAnsiBuf[12];
  557. DWORD dwDisableCatsearch=0;
  558. switch( dwStructureType ) {
  559. case AFP_VOLUME_STRUCT:
  560. pAfpMultiSz = AfpVolumeMultiSz;
  561. cbStructSize = sizeof( AFP_VOLUME_INFO );
  562. //
  563. // The following "quick fix" is for Disabling CatSearch support. Read in the
  564. // DisableCatsearch parameter if it's put in. In most cases, this parm won't
  565. // be there. If it is, the server disables CatSearch
  566. //
  567. for ( (lpwchWalker = (LPWSTR)pbMultiSz);
  568. (*lpwchWalker != TEXT('\0') );
  569. (lpwchWalker += ( STRLEN( lpwchWalker ) + 1 ) ))
  570. {
  571. if ( STRNICMP( AFPREG_VALNAME_CATSEARCH,
  572. lpwchWalker,
  573. STRLEN( AFPREG_VALNAME_CATSEARCH ) ) == 0 )
  574. {
  575. lpwchWalker += ( STRLEN( AFPREG_VALNAME_CATSEARCH ) + 1 );
  576. wcstombs( chAnsiBuf, lpwchWalker, sizeof(chAnsiBuf) );
  577. dwDisableCatsearch = atoi( chAnsiBuf );
  578. break;
  579. }
  580. }
  581. break;
  582. case AFP_EXTENSION_STRUCT:
  583. pAfpMultiSz = AfpExtensionMultiSz;
  584. cbStructSize = sizeof( AFP_EXTENSION );
  585. break;
  586. case AFP_TYPECREATOR_STRUCT:
  587. pAfpMultiSz = AfpTypeCreatorMultiSz;
  588. cbStructSize = sizeof( AFP_TYPE_CREATOR );
  589. break;
  590. case AFP_ICON_STRUCT:
  591. pAfpMultiSz = AfpIconMultiSz;
  592. cbStructSize = sizeof( AFP_ICON_INFO );
  593. break;
  594. default:
  595. return( ERROR_INVALID_PARAMETER );
  596. }
  597. ZeroMemory( pbStructure, cbStructSize );
  598. // For every field in the structure
  599. //
  600. for ( dwIndex = 0; pAfpMultiSz[dwIndex].dwType != REG_NONE; dwIndex++ ){
  601. // This is the value name so do not try to retrieve it from the
  602. // buffer.
  603. //
  604. if ( pAfpMultiSz[dwIndex].lpwsValueName == NULL )
  605. continue;
  606. // Search for valuename for this field
  607. //
  608. for ( lpwchWalker = (LPWSTR)pbMultiSz;
  609. ( *lpwchWalker != TEXT('\0') )
  610. &&
  611. ( STRNICMP( pAfpMultiSz[dwIndex].lpwsValueName,
  612. lpwchWalker,
  613. STRLEN(pAfpMultiSz[dwIndex].lpwsValueName) ) != 0 );
  614. lpwchWalker += ( STRLEN( lpwchWalker ) + 1 ) );
  615. // Could not find parameter
  616. //
  617. if ( *lpwchWalker == TEXT('\0') )
  618. return( ERROR_INVALID_PARAMETER );
  619. // Otherwise we found it so get the value
  620. //
  621. lpwchWalker += ( STRLEN( pAfpMultiSz[dwIndex].lpwsValueName ) + 1 );
  622. pData = pbStructure + pAfpMultiSz[dwIndex].dwOffset;
  623. // If there is no value after the value name then ignore this field
  624. // It defaults to zero.
  625. //
  626. if ( *lpwchWalker != TEXT( '\0' ) ) {
  627. // Convert to integer
  628. //
  629. if ( pAfpMultiSz[dwIndex].dwType == REG_DWORD ) {
  630. wcstombs( chAnsiBuf, lpwchWalker, sizeof(chAnsiBuf) );
  631. *((LPDWORD)pData) = atoi( chAnsiBuf );
  632. }
  633. //
  634. // CatSearch hack continued: if we are looking at the volume mask
  635. // parameter, see if we must turn the bit off.
  636. //
  637. if( dwStructureType == AFP_VOLUME_STRUCT && dwDisableCatsearch )
  638. {
  639. if ( STRNICMP( pAfpMultiSz[dwIndex].lpwsValueName,
  640. AFPREG_VALNAME_PROPS,
  641. STRLEN(pAfpMultiSz[dwIndex].lpwsValueName) ) == 0 )
  642. {
  643. *((LPDWORD)pData) |= AFP_VOLUME_DISALLOW_CATSRCH;
  644. }
  645. }
  646. if ( pAfpMultiSz[dwIndex].dwType == REG_SZ ) {
  647. // Check if this is a pointer or an in-place buffer
  648. //
  649. if ( pAfpMultiSz[dwIndex].fIsInPlace ) {
  650. if ( STRLEN( lpwchWalker ) > pAfpMultiSz[dwIndex].cch )
  651. return( ERROR_INVALID_PARAMETER );
  652. STRCPY( (LPWSTR)pData, lpwchWalker );
  653. }
  654. else
  655. *((LPWSTR*)pData) = lpwchWalker;
  656. }
  657. }
  658. }
  659. return( NO_ERROR );
  660. }
  661. //**
  662. //
  663. // Call: AfpBufMakeFSDETCMappings
  664. //
  665. // Returns: NO_ERROR
  666. // ERROR_NOT_ENOUGH_MEMORY
  667. //
  668. // Description: This routine will convert all the mappings in the
  669. // form stored in AfpGlobals.AfpETCMapInfo to the form
  670. // required by the FSD, ie. the ETCMAPINFO structure.
  671. // It is the responsibility for the caller to free
  672. // allocated memory.
  673. //
  674. DWORD
  675. AfpBufMakeFSDETCMappings(
  676. OUT PSRVETCPKT *ppSrvSetEtc,
  677. OUT LPDWORD lpdwSrvSetEtcBufSize
  678. )
  679. {
  680. DWORD dwIndex;
  681. PETCMAPINFO2 pETCMapInfo;
  682. PAFP_EXTENSION pExtensionWalker;
  683. PAFP_TYPE_CREATOR pTypeCreator;
  684. AFP_TYPE_CREATOR AfpTypeCreatorKey;
  685. DWORD dwNumTypeCreators;
  686. // Allocate space to hold the ETCMaps in the form required by the FSD.
  687. //
  688. *ppSrvSetEtc = (PSRVETCPKT)LocalAlloc( LPTR,
  689. AFP_FIELD_SIZE( SRVETCPKT, retc_NumEtcMaps ) +
  690. (AfpGlobals.AfpETCMapInfo.afpetc_num_extensions*sizeof(ETCMAPINFO2)));
  691. if ( *ppSrvSetEtc == NULL )
  692. return( ERROR_NOT_ENOUGH_MEMORY );
  693. // Walk through the extension list
  694. //
  695. for( dwIndex = 0,
  696. pETCMapInfo = (*ppSrvSetEtc)->retc_EtcMaps,
  697. pExtensionWalker = AfpGlobals.AfpETCMapInfo.afpetc_extension,
  698. pTypeCreator = AfpGlobals.AfpETCMapInfo.afpetc_type_creator,
  699. dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators,
  700. (*ppSrvSetEtc)->retc_NumEtcMaps = 0;
  701. dwIndex < AfpGlobals.AfpETCMapInfo.afpetc_num_extensions;
  702. dwIndex++,
  703. dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators,
  704. pExtensionWalker++
  705. ) {
  706. // Ignore any extensions that are associated with the default
  707. // type/creator. They shouldnt be in the registry to begin with.
  708. //
  709. if ( pExtensionWalker->afpe_tcid == AFP_DEF_TCID )
  710. continue;
  711. // Find the type/creator associated with this extension.
  712. //
  713. AfpTypeCreatorKey.afptc_id = pExtensionWalker->afpe_tcid;
  714. pTypeCreator = _lfind( &AfpTypeCreatorKey,
  715. AfpGlobals.AfpETCMapInfo.afpetc_type_creator,
  716. (unsigned int *)&dwNumTypeCreators,
  717. sizeof(AFP_TYPE_CREATOR),
  718. AfpLCompareTypeCreator );
  719. // If there is a type/creator associated with this extension
  720. //
  721. if ( pTypeCreator != NULL ) {
  722. AfpBufCopyFSDETCMapInfo( pTypeCreator,
  723. pExtensionWalker,
  724. pETCMapInfo );
  725. pETCMapInfo++;
  726. (*ppSrvSetEtc)->retc_NumEtcMaps++;
  727. }
  728. }
  729. *lpdwSrvSetEtcBufSize = AFP_FIELD_SIZE( SRVETCPKT, retc_NumEtcMaps ) +
  730. ((*ppSrvSetEtc)->retc_NumEtcMaps * sizeof(ETCMAPINFO2));
  731. return( NO_ERROR );
  732. }
  733. //**
  734. //
  735. // Call: AfpBufMakeFSDIcon
  736. //
  737. // Returns: none.
  738. //
  739. // Description: This routine will copy the icon information from the
  740. // AFP_ICON_INFO data structure to an SRVICONINFO data
  741. // structure viz. the form that the FSD needs.
  742. //
  743. VOID
  744. AfpBufMakeFSDIcon(
  745. IN PAFP_ICON_INFO pIconInfo,
  746. OUT LPBYTE lpbFSDIcon,
  747. OUT LPDWORD lpcbFSDIconSize
  748. )
  749. {
  750. UCHAR chBuffer[sizeof(AFP_ICON_INFO)]; // Need enough space to translate
  751. // Blank out the whole structure so that type and creator will
  752. // be padded with blanks
  753. //
  754. memset( lpbFSDIcon, ' ', sizeof(SRVICONINFO) );
  755. // Convert to ANSI and copy type
  756. //
  757. wcstombs(chBuffer,pIconInfo->afpicon_type,sizeof(chBuffer));
  758. CopyMemory( ((PSRVICONINFO)lpbFSDIcon)->icon_type,
  759. chBuffer,
  760. STRLEN(pIconInfo->afpicon_type));
  761. // Convert to ANSI copy creator
  762. //
  763. wcstombs(chBuffer,pIconInfo->afpicon_creator,sizeof(chBuffer));
  764. CopyMemory( ((PSRVICONINFO)lpbFSDIcon)->icon_creator,
  765. chBuffer,
  766. STRLEN(pIconInfo->afpicon_creator));
  767. // Set icon type
  768. //
  769. ((PSRVICONINFO)lpbFSDIcon)->icon_icontype = pIconInfo->afpicon_icontype;
  770. // Set icon data length
  771. //
  772. ((PSRVICONINFO)lpbFSDIcon)->icon_length = pIconInfo->afpicon_length;
  773. CopyMemory( lpbFSDIcon + sizeof(SRVICONINFO),
  774. pIconInfo->afpicon_data,
  775. ((PSRVICONINFO)lpbFSDIcon)->icon_length );
  776. *lpcbFSDIconSize = sizeof(SRVICONINFO) + pIconInfo->afpicon_length;
  777. return;
  778. }
  779. //**
  780. //
  781. // Call: AfpBufCopyFSDETCMapInfo
  782. //
  783. // Returns: none
  784. //
  785. // Description: This routine will copu information from the AFP_TYPE_CREATOR
  786. // and AFP_EXTENSION data structures into a ETCMAPINFO data
  787. // structure viz. in the form as required by the FSD.
  788. //
  789. VOID
  790. AfpBufCopyFSDETCMapInfo(
  791. IN PAFP_TYPE_CREATOR pAfpTypeCreator,
  792. IN PAFP_EXTENSION pAfpExtension,
  793. OUT PETCMAPINFO2 pFSDETCMapInfo
  794. )
  795. {
  796. CHAR Buffer[sizeof(AFP_TYPE_CREATOR)];
  797. // Insert blanks which will be used to pad type/creators less
  798. // than their max. lengths.
  799. //
  800. memset( (LPBYTE)pFSDETCMapInfo, ' ', sizeof(ETCMAPINFO2) );
  801. ZeroMemory( (LPBYTE)(pFSDETCMapInfo->etc_extension),
  802. AFP_FIELD_SIZE( ETCMAPINFO2, etc_extension ) );
  803. CopyMemory( pFSDETCMapInfo->etc_extension,
  804. pAfpExtension->afpe_extension,
  805. wcslen(pAfpExtension->afpe_extension) * sizeof(WCHAR));
  806. wcstombs( Buffer, pAfpTypeCreator->afptc_type, sizeof(Buffer) );
  807. CopyMemory( pFSDETCMapInfo->etc_type,
  808. Buffer,
  809. STRLEN(pAfpTypeCreator->afptc_type));
  810. wcstombs( Buffer, pAfpTypeCreator->afptc_creator, sizeof(Buffer) );
  811. CopyMemory( pFSDETCMapInfo->etc_creator,
  812. Buffer,
  813. STRLEN(pAfpTypeCreator->afptc_creator));
  814. return;
  815. }
  816. //**
  817. //
  818. // Call: AfpBufUnicodeToNibble
  819. //
  820. // Returns: NO_ERROR
  821. // ERROR_INVALID_PARAMETER
  822. //
  823. // Description: This routine will take a pointer to a UNCODE string and
  824. // convert each UNICODE char to a the corresponding nibble.
  825. // it char. 'A' will be converted to a nibble having value 0xA
  826. // This conversion is done in-place.
  827. //
  828. DWORD
  829. AfpBufUnicodeToNibble(
  830. IN OUT LPWSTR lpwsData
  831. )
  832. {
  833. DWORD dwIndex;
  834. BYTE bData;
  835. LPBYTE lpbData = (LPBYTE)lpwsData;
  836. // Convert each UNICODE character to nibble. (in place)
  837. //
  838. for ( dwIndex = 0; *lpwsData != TEXT('\0'); dwIndex++, lpwsData++ ) {
  839. if ( iswalpha( *lpwsData ) ) {
  840. if ( iswupper( *lpwsData ) )
  841. bData = *lpwsData - TEXT('A');
  842. else
  843. bData = *lpwsData - TEXT('a');
  844. bData += 10;
  845. if ( bData > 0x0F )
  846. return( ERROR_INVALID_PARAMETER );
  847. }
  848. else if ( iswdigit( *lpwsData ) )
  849. bData = *lpwsData - TEXT('0');
  850. else
  851. return( ERROR_INVALID_PARAMETER );
  852. // Multipy so that data is in the most significant nibble.
  853. // Do this every other time.
  854. //
  855. if ( ( dwIndex % 2 ) == 0 )
  856. *lpbData = bData * 16;
  857. else {
  858. *lpbData += bData;
  859. lpbData++;
  860. }
  861. }
  862. return( NO_ERROR );
  863. }
  864. //**
  865. //
  866. // Call: AfpBCompareTypeCreator
  867. //
  868. // Returns: < 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
  869. // > 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
  870. // == 0 if pAfpTypeCreator1 is equal to pAfpTypeCreator2
  871. //
  872. // Description: This routine is called by qsort to sort the list of
  873. // type creators in the cache. The list is sorted in
  874. // ascending alphabetical order of the concatenation of the
  875. // creator and type. This list is sorted to facilitate quick
  876. // lookup (binary search). This routine is also called by
  877. // bsearch to do a binary search on the list.
  878. //
  879. int
  880. _cdecl
  881. AfpBCompareTypeCreator(
  882. IN const void * pAfpTypeCreator1,
  883. IN const void * pAfpTypeCreator2
  884. )
  885. {
  886. WCHAR wchTypeCreator1[ sizeof( AFP_TYPE_CREATOR )];
  887. WCHAR wchTypeCreator2[ sizeof( AFP_TYPE_CREATOR )];
  888. STRCPY(wchTypeCreator1,
  889. ((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_creator);
  890. if (STRLEN(((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_creator) == 0)
  891. wchTypeCreator1[0]=L'\0';
  892. STRCAT(wchTypeCreator1,((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_type );
  893. STRCPY(wchTypeCreator2,
  894. ((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_creator);
  895. STRCAT(wchTypeCreator2,((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_type );
  896. return( STRCMP( wchTypeCreator1, wchTypeCreator2 ) );
  897. }
  898. //**
  899. //
  900. // Call: AfpLCompareTypeCreator
  901. //
  902. // Returns: < 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
  903. // > 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
  904. // == 0 if pAfpTypeCreator1 is equal to pAfpTypeCreator2
  905. //
  906. // Description: This routine is called by lfind to do a linear search of
  907. // the type/creator list.
  908. //
  909. int
  910. _cdecl
  911. AfpLCompareTypeCreator(
  912. IN const void * pAfpTypeCreator1,
  913. IN const void * pAfpTypeCreator2
  914. )
  915. {
  916. return( ( ((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_id ==
  917. ((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_id ) ? 0 : 1 );
  918. }
  919. //**
  920. //
  921. // Call: AfpBCompareExtension
  922. //
  923. // Returns: < 0 if pAfpExtension1 comes before pAfpExtension2
  924. // > 0 if pAfpExtension1 comes before pAfpExtension2
  925. // == 0 if pAfpExtension1 is equal to pAfpExtension2
  926. //
  927. // Description: This is called by qsort to sort the list of extensions in the
  928. // cache. The list is sorted by ID. This routine is also called
  929. // by bserach to do a binary lookup of this list.
  930. //
  931. int
  932. _cdecl
  933. AfpBCompareExtension(
  934. IN const void * pAfpExtension1,
  935. IN const void * pAfpExtension2
  936. )
  937. {
  938. return((((PAFP_EXTENSION)pAfpExtension1)->afpe_tcid ==
  939. ((PAFP_EXTENSION)pAfpExtension2)->afpe_tcid ) ? 0 :
  940. ((((PAFP_EXTENSION)pAfpExtension1)->afpe_tcid <
  941. ((PAFP_EXTENSION)pAfpExtension2)->afpe_tcid ) ? -1 : 1 ));
  942. }
  943. //**
  944. //
  945. // Call: AfpLCompareExtension
  946. //
  947. // Returns: < 0 if pAfpExtension1 comes before pAfpExtension2
  948. // > 0 if pAfpExtension1 comes before pAfpExtension2
  949. // == 0 if pAfpExtension1 is equal to pAfpExtension2
  950. //
  951. // Description: This routine is called by lfind to do a linear lookup of the
  952. // list of extensions in the cache.
  953. //
  954. int
  955. _cdecl
  956. AfpLCompareExtension(
  957. IN const void * pAfpExtension1,
  958. IN const void * pAfpExtension2
  959. )
  960. {
  961. return( STRICMP( ((PAFP_EXTENSION)pAfpExtension1)->afpe_extension,
  962. ((PAFP_EXTENSION)pAfpExtension2)->afpe_extension ) );
  963. }
  964. //**
  965. //
  966. // Call: AfpBinarySearch
  967. //
  968. // Returns: Pointer to first occurance of element that matches pKey.
  969. //
  970. // Description: This is a wrapper around bsearch. Since bsearch does not
  971. // return the first occurance of an element within the array,
  972. // this routine will back up to point to the first occurance
  973. // of a record with a particular key is reached.
  974. //
  975. void *
  976. AfpBinarySearch(
  977. IN const void * pKey,
  978. IN const void * pBase,
  979. IN size_t num,
  980. IN size_t width,
  981. IN int (_cdecl *compare)(const void * pElem1, const void * pElem2 )
  982. )
  983. {
  984. void * pCurrElem = bsearch( pKey, pBase, num, width, compare);
  985. if ( pCurrElem == NULL )
  986. return( NULL );
  987. // Backup until first occurance is reached
  988. //
  989. while ( ( (ULONG_PTR)pCurrElem > (ULONG_PTR)pBase )
  990. &&
  991. ( (*compare)( pKey, (void*)((ULONG_PTR)pCurrElem - width) ) == 0 ) )
  992. pCurrElem = (void *)((ULONG_PTR)pCurrElem - width);
  993. return( pCurrElem );
  994. }