KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > smb > dcerpc > DCEBuffer


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.smb.dcerpc;
18
19 import org.alfresco.filesys.smb.NTTime;
20 import org.alfresco.filesys.smb.SMBStatus;
21 import org.alfresco.filesys.smb.TransactBuffer;
22 import org.alfresco.filesys.util.DataBuffer;
23 import org.alfresco.filesys.util.DataPacker;
24 import org.alfresco.filesys.util.HexDump;
25
26 /**
27  * DCE Buffer Class
28  */

29 public class DCEBuffer
30 {
31
32     // Header value types
33

34     public static final int HDR_VERMAJOR = 0;
35     public static final int HDR_VERMINOR = 1;
36     public static final int HDR_PDUTYPE = 2;
37     public static final int HDR_FLAGS = 3;
38     public static final int HDR_DATAREP = 4;
39     public static final int HDR_FRAGLEN = 5;
40     public static final int HDR_AUTHLEN = 6;
41     public static final int HDR_CALLID = 7;
42     public static final int HDR_ALLOCHINT = 8;
43     public static final int HDR_OPCODE = 9;
44     
45     // Header flags
46

47     public static final int FLG_FIRSTFRAG = 0x01;
48     public static final int FLG_LASTFRAG = 0x02;
49     public static final int FLG_CANCEL = 0x04;
50     public static final int FLG_IDEMPOTENT = 0x20;
51     public static final int FLG_BROADCAST = 0x40;
52     
53     public static final int FLG_ONLYFRAG = 0x03;
54     
55     // DCE/RPC header offsets
56

57     public static final int VERSIONMAJOR = 0;
58     public static final int VERSIONMINOR = 1;
59     public static final int PDUTYPE = 2;
60     public static final int HEADERFLAGS = 3;
61     public static final int PACKEDDATAREP = 4;
62     public static final int FRAGMENTLEN = 8;
63     public static final int AUTHLEN = 10;
64     public static final int CALLID = 12;
65     public static final int DCEDATA = 16;
66     
67     // DCE/RPC Request offsets
68

69     public static final int ALLOCATIONHINT = 16;
70     public static final int PRESENTIDENT = 20;
71     public static final int OPERATIONID = 22;
72     public static final int OPERATIONDATA = 24;
73     
74     // DCE/RPC header constants
75

76     private static final byte VAL_VERSIONMAJOR = 5;
77     private static final byte VAL_VERSIONMINOR = 0;
78     private static final int VAL_PACKEDDATAREP = 0x00000010;
79     
80     // Data alignment types
81

82     public final static int ALIGN_NONE = -1;
83     public final static int ALIGN_SHORT = 0;
84     public final static int ALIGN_INT = 1;
85     public final static int ALIGN_LONG = 2;
86     
87     // Maximum string length
88

89     public final static int MAX_STRING_LEN = 1000;
90     
91     // Alignment masks and rounding
92

93     private final static int[] _alignMask = { 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8 };
94     private final static int[] _alignRound = { 1, 3, 7 };
95     
96     // Default buffer allocation
97

98     private static final int DEFAULT_BUFSIZE = 8192;
99
100     // Maximum buffer size, used when the buffer is reset to release large buffers
101

102     private static final int MAX_BUFFER_SIZE = 65536;
103     
104     // Dummy address value to use for pointers within the buffer
105

106     private static final int DUMMY_ADDRESS = 0x12345678;
107         
108     // Data buffer and current read/write positions
109

110     private byte[] m_buffer;
111     private int m_base;
112     private int m_pos;
113     private int m_rdpos;
114
115     // Error status
116

117     private int m_errorCode;
118
119     /**
120      * Default constructor
121      */

122     public DCEBuffer()
123     {
124         m_buffer = new byte[DEFAULT_BUFSIZE];
125         m_pos = 0;
126         m_rdpos = 0;
127         m_base = 0;
128     }
129
130     /**
131      * Class constructor
132      *
133      * @param siz int
134      */

135     public DCEBuffer(int siz)
136     {
137         m_buffer = new byte[siz];
138         m_pos = 0;
139         m_rdpos = 0;
140         m_base = 0;
141     }
142
143     /**
144      * Class constructor
145      *
146      * @param buf byte[]
147      * @param startPos int
148      * @param len int
149      */

150     public DCEBuffer(byte[] buf, int startPos, int len)
151     {
152         m_buffer = buf;
153         m_pos = startPos + len;
154         m_rdpos = startPos;
155         m_base = startPos;
156     }
157
158     /**
159      * Class constructor
160      *
161      * @param buf byte[]
162      * @param startPos int
163      */

164     public DCEBuffer(byte[] buf, int startPos)
165     {
166         m_buffer = buf;
167         m_pos = startPos;
168         m_rdpos = startPos;
169         m_base = startPos;
170     }
171
172     /**
173      * Class constructor
174      *
175      * @param tbuf TransactBuffer
176      */

177     public DCEBuffer(TransactBuffer tbuf)
178     {
179         DataBuffer dataBuf = tbuf.getDataBuffer();
180         m_buffer = dataBuf.getBuffer();
181         m_rdpos = dataBuf.getOffset();
182         m_base = dataBuf.getOffset();
183         m_pos = m_rdpos + dataBuf.getLength();
184     }
185
186     /**
187      * Return the DCE buffer
188      *
189      * @return byte[]
190      */

191     public final byte[] getBuffer()
192     {
193         return m_buffer;
194     }
195
196     /**
197      * Return the current used buffer length
198      *
199      * @return int
200      */

201     public final int getLength()
202     {
203         return m_pos;
204     }
205
206     /**
207      * Return the read buffer position
208      *
209      * @return int
210      */

211     public final int getReadPosition()
212     {
213         return m_rdpos;
214     }
215
216     /**
217      * Return the write buffer position
218      *
219      * @return int
220      */

221     public final int getWritePosition()
222     {
223         return m_pos;
224     }
225
226     /**
227      * Return the amount of data left to read
228      *
229      * @return int
230      */

231     public final int getAvailableLength()
232     {
233         return m_pos - m_rdpos;
234     }
235
236     /**
237      * Get a byte from the buffer
238      *
239      * @param align int
240      * @return int
241      * @exception DCEBufferException
242      */

243     public final int getByte(int align) throws DCEBufferException
244     {
245
246         // Check if there is enough data in the buffer
247

248         if (m_buffer.length - m_rdpos < 1)
249             throw new DCEBufferException("End of DCE buffer");
250
251         // Unpack the integer value
252

253         int bval = (int) (m_buffer[m_rdpos++] & 0xFF);
254         alignRxPosition(align);
255         return bval;
256     }
257
258     /**
259      * Get a block of bytes from the buffer
260      *
261      * @param buf byte[]
262      * @param len int
263      * @return byte[]
264      * @throws DCEBufferException
265      */

266     public final byte[] getBytes(byte[] buf, int len) throws DCEBufferException
267     {
268
269         // Check if there is enough data in the buffer
270

271         if (m_buffer.length - m_rdpos < len)
272             throw new DCEBufferException("End of DCE buffer");
273
274         // Check if a return buffer should be allocated
275

276         if (buf == null)
277             buf = new byte[len];
278
279         // Unpack the bytes
280

281         for (int i = 0; i < len; i++)
282             buf[i] = m_buffer[m_rdpos++];
283         return buf;
284     }
285
286     /**
287      * Get a short from the buffer
288      *
289      * @return int
290      * @exception DCEBufferException
291      */

292     public final int getShort() throws DCEBufferException
293     {
294
295         // Check if there is enough data in the buffer
296

297         if (m_buffer.length - m_rdpos < 2)
298             throw new DCEBufferException("End of DCE buffer");
299
300         // Unpack the integer value
301

302         int sval = (int) DataPacker.getIntelShort(m_buffer, m_rdpos);
303         m_rdpos += 2;
304         return sval;
305     }
306
307     /**
308      * Get a short from the buffer and align the read pointer
309      *
310      * @param align int
311      * @return int
312      * @exception DCEBufferException
313      */

314     public final int getShort(int align) throws DCEBufferException
315     {
316
317         // Read the short
318

319         int sval = getShort();
320
321         // Align the read position
322

323         alignRxPosition(align);
324
325         // Return the short value
326

327         return sval;
328     }
329
330     /**
331      * Get an integer from the buffer
332      *
333      * @return int
334      * @exception DCEBufferException
335      */

336     public final int getInt() throws DCEBufferException
337     {
338
339         // Check if there is enough data in the buffer
340

341         if (m_buffer.length - m_rdpos < 4)
342             throw new DCEBufferException("End of DCE buffer");
343
344         // Unpack the integer value
345

346         int ival = DataPacker.getIntelInt(m_buffer, m_rdpos);
347         m_rdpos += 4;
348         return ival;
349     }
350
351     /**
352      * Get a pointer from the buffer
353      *
354      * @return int
355      * @exception DCEBufferException
356      */

357     public final int getPointer() throws DCEBufferException
358     {
359         return getInt();
360     }
361
362     /**
363      * Get a pointer from the buffer and return either an empty string if the pointer is valid or
364      * null.
365      *
366      * @return String
367      * @exception DCEBufferException
368      */

369     public final String JavaDoc getStringPointer() throws DCEBufferException
370     {
371         if (getInt() == 0)
372             return null;
373         return "";
374     }
375
376     /**
377      * Get a character array header from the buffer and return either an empty string if the pointer
378      * is valid or null.
379      *
380      * @return String
381      * @exception DCEBufferException
382      */

383     public final String JavaDoc getCharArrayPointer() throws DCEBufferException
384     {
385
386         // Get the array length and size
387

388         int len = getShort();
389         int siz = getShort();
390         return getStringPointer();
391     }
392
393     /**
394      * Get a character array from the buffer if the String variable is not null, and align on the
395      * specified boundary
396      *
397      * @param strVar String
398      * @param align int
399      * @return String
400      * @exception DCEBufferException
401      */

402     public final String JavaDoc getCharArrayNotNull(String JavaDoc strVar, int align) throws DCEBufferException
403     {
404
405         // Check if the string variable is not null
406

407         String JavaDoc str = "";
408
409         if (strVar != null)
410         {
411
412             // Read the string
413

414             str = getCharArray();
415
416             // Align the read position
417

418             alignRxPosition(align);
419         }
420
421         // Return the string
422

423         return str;
424     }
425
426     /**
427      * Get a long (64 bit) value from the buffer
428      *
429      * @return long
430      * @exception DCEBufferException
431      */

432     public final long getLong() throws DCEBufferException
433     {
434
435         // Check if there is enough data in the buffer
436

437         if (m_buffer.length - m_rdpos < 8)
438             throw new DCEBufferException("End of DCE buffer");
439
440         // Unpack the integer value
441

442         long lval = DataPacker.getIntelLong(m_buffer, m_rdpos);
443         m_rdpos += 8;
444         return lval;
445     }
446
447     /**
448      * Return a DCE/RPC header value
449      *
450      * @param valTyp int
451      * @return int
452      */

453     public final int getHeaderValue(int valTyp)
454     {
455
456         int result = -1;
457
458         switch (valTyp)
459         {
460
461         // Version major
462

463         case HDR_VERMAJOR:
464             result = (int) (m_buffer[m_base + VERSIONMAJOR] & 0xFF);
465             break;
466
467         // Version minor
468

469         case HDR_VERMINOR:
470             result = (int) (m_buffer[m_base + VERSIONMINOR] & 0xFF);
471             break;
472
473         // PDU type
474

475         case HDR_PDUTYPE:
476             result = (int) (m_buffer[m_base + PDUTYPE] & 0xFF);
477             break;
478
479         // Flags
480

481         case HDR_FLAGS:
482             result = (int) (m_buffer[m_base + HEADERFLAGS] & 0xFF);
483             break;
484
485         // Data representation
486

487         case HDR_DATAREP:
488             result = DataPacker.getIntelInt(m_buffer, m_base + VERSIONMINOR);
489             break;
490
491         // Authorisation length
492

493         case HDR_AUTHLEN:
494             result = DataPacker.getIntelInt(m_buffer, m_base + AUTHLEN);
495             break;
496
497         // Fragment length
498

499         case HDR_FRAGLEN:
500             result = DataPacker.getIntelInt(m_buffer, m_base + FRAGMENTLEN);
501             break;
502
503         // Call id
504

505         case HDR_CALLID:
506             result = DataPacker.getIntelInt(m_buffer, m_base + CALLID);
507             break;
508
509         // Request allocation hint
510

511         case HDR_ALLOCHINT:
512             result = DataPacker.getIntelInt(m_buffer, m_base + ALLOCATIONHINT);
513             break;
514
515         // Request opcode
516

517         case HDR_OPCODE:
518             result = DataPacker.getIntelShort(m_buffer, m_base + OPERATIONID);
519             break;
520         }
521
522         // Return the header value
523

524         return result;
525     }
526
527     /**
528      * Set a DCE/RPC header value
529      *
530      * @param typ int
531      * @param val int
532      */

533     public final void setHeaderValue(int typ, int val)
534     {
535
536         switch (typ)
537         {
538
539         // Version major
540

541         case HDR_VERMAJOR:
542             m_buffer[m_base + VERSIONMAJOR] = (byte) (val & 0xFF);
543             break;
544
545         // Version minor
546

547         case HDR_VERMINOR:
548             m_buffer[m_base + VERSIONMINOR] = (byte) (val & 0xFF);
549             break;
550
551         // PDU type
552

553         case HDR_PDUTYPE:
554             m_buffer[m_base + PDUTYPE] = (byte) (val & 0xFF);
555             break;
556
557         // Flags
558

559         case HDR_FLAGS:
560             m_buffer[m_base + HEADERFLAGS] = (byte) (val & 0xFF);
561             break;
562
563         // Data representation
564

565         case HDR_DATAREP:
566             DataPacker.putIntelInt(val, m_buffer, m_base + PACKEDDATAREP);
567             break;
568
569         // Authorisation length
570

571         case HDR_AUTHLEN:
572             DataPacker.putIntelInt(val, m_buffer, m_base + AUTHLEN);
573             break;
574
575         // Fragment length
576

577         case HDR_FRAGLEN:
578             DataPacker.putIntelInt(val, m_buffer, m_base + FRAGMENTLEN);
579             break;
580
581         // Call id
582

583         case HDR_CALLID:
584             DataPacker.putIntelInt(val, m_buffer, m_base + CALLID);
585             break;
586
587         // Request allocation hint
588

589         case HDR_ALLOCHINT:
590             DataPacker.putIntelInt(val, m_buffer, m_base + ALLOCATIONHINT);
591             break;
592
593         // Request opcode
594

595         case HDR_OPCODE:
596             DataPacker.putIntelShort(val, m_buffer, m_base + OPERATIONID);
597             break;
598         }
599     }
600
601     /**
602      * Determine if this is the first fragment
603      *
604      * @return boolean
605      */

606     public final boolean isFirstFragment()
607     {
608         if ((getHeaderValue(HDR_FLAGS) & FLG_FIRSTFRAG) != 0)
609             return true;
610         return false;
611     }
612
613     /**
614      * Determine if this is the last fragment
615      *
616      * @return boolean
617      */

618     public final boolean isLastFragment()
619     {
620         if ((getHeaderValue(HDR_FLAGS) & FLG_LASTFRAG) != 0)
621             return true;
622         return false;
623     }
624
625     /**
626      * Determine if this is the only fragment in the request
627      *
628      * @return boolean
629      */

630     public final boolean isOnlyFragment()
631     {
632         if ((getHeaderValue(HDR_FLAGS) & FLG_ONLYFRAG) == FLG_ONLYFRAG)
633             return true;
634         return false;
635     }
636
637     /**
638      * Check if the status indicates that there are more entries available
639      *
640      * @return boolean
641      */

642     public final boolean hasMoreEntries()
643     {
644         return getStatusCode() == SMBStatus.Win32MoreEntries ? true : false;
645     }
646
647     /**
648      * Check if the status indicates success
649      *
650      * @return boolean
651      */

652     public final boolean hasSuccessStatus()
653     {
654         return getStatusCode() == SMBStatus.NTSuccess ? true : false;
655     }
656
657     /**
658      * Skip over a number of bytes
659      *
660      * @param cnt int
661      * @exception DCEBufferException
662      */

663     public final void skipBytes(int cnt) throws DCEBufferException
664     {
665
666         // Check if there is enough data in the buffer
667

668         if (m_buffer.length - m_rdpos < cnt)
669             throw new DCEBufferException("End of DCE buffer");
670
671         // Skip bytes
672

673         m_rdpos += cnt;
674     }
675
676     /**
677      * Skip over a pointer
678      *
679      * @exception DCEBufferException
680      */

681     public final void skipPointer() throws DCEBufferException
682     {
683
684         // Check if there is enough data in the buffer
685

686         if (m_buffer.length - m_rdpos < 4)
687             throw new DCEBufferException("End of DCE buffer");
688
689         // Skip the 32bit pointer value
690

691         m_rdpos += 4;
692     }
693
694     /**
695      * Set the read position
696      *
697      * @param pos int
698      * @exception DCEBufferException
699      */

700     public final void positionAt(int pos) throws DCEBufferException
701     {
702
703         // Check if there is enough data in the buffer
704

705         if (m_buffer.length < pos)
706             throw new DCEBufferException("End of DCE buffer");
707
708         // Set the read position
709

710         m_rdpos = pos;
711     }
712
713     /**
714      * Get a number of Unicode characters from the buffer and return as a string
715      *
716      * @param len int
717      * @return String
718      * @exception DCEBufferException
719      */

720     public final String JavaDoc getChars(int len) throws DCEBufferException
721     {
722
723         // Check if there is enough data in the buffer
724

725         if (m_buffer.length - m_rdpos < (len * 2))
726             throw new DCEBufferException("End of DCE buffer");
727
728         // Build up the return string
729

730         StringBuffer JavaDoc str = new StringBuffer JavaDoc(len);
731         char curChar;
732
733         while (len-- > 0)
734         {
735
736             // Get a Unicode character from the buffer
737

738             curChar = (char) ((m_buffer[m_rdpos + 1] << 8) + m_buffer[m_rdpos]);
739             m_rdpos += 2;
740
741             // Add the character to the string
742

743             str.append(curChar);
744         }
745
746         // Return the string
747

748         return str.toString();
749     }
750
751     /**
752      * Get the status code from the end of the data block
753      *
754      * @return int
755      */

756     public final int getStatusCode()
757     {
758
759         // Read the integer value at the end of the buffer
760

761         int ival = DataPacker.getIntelInt(m_buffer, m_pos - 4);
762         return ival;
763     }
764
765     /**
766      * Get a string from the buffer
767      *
768      * @return String
769      * @exception DCEBufferException
770      */

771     public final String JavaDoc getString() throws DCEBufferException
772     {
773
774         // Check if there is enough data in the buffer
775

776         if (m_buffer.length - m_rdpos < 12)
777             throw new DCEBufferException("End of DCE buffer");
778
779         // Unpack the string
780

781         int maxLen = getInt();
782         skipBytes(4); // offset
783
int strLen = getInt();
784
785         String JavaDoc str = DataPacker.getUnicodeString(m_buffer, m_rdpos, strLen);
786         m_rdpos += (strLen * 2);
787         return str;
788     }
789
790     /**
791      * Get a character array from the buffer
792      *
793      * @return String
794      * @exception DCEBufferException
795      */

796     public final String JavaDoc getCharArray() throws DCEBufferException
797     {
798
799         // Check if there is enough data in the buffer
800

801         if (m_buffer.length - m_rdpos < 12)
802             throw new DCEBufferException("End of DCE buffer");
803
804         // Unpack the string
805

806         int maxLen = getInt();
807         skipBytes(4); // offset
808
int strLen = getInt(); // in unicode chars
809

810         String JavaDoc str = null;
811         if (strLen > 0)
812         {
813             str = DataPacker.getUnicodeString(m_buffer, m_rdpos, strLen);
814             m_rdpos += (strLen * 2);
815         }
816         return str;
817     }
818
819     /**
820      * Get a character array from the buffer and align on the specified boundary
821      *
822      * @param align int
823      * @return String
824      * @exception DCEBufferException
825      */

826     public final String JavaDoc getCharArray(int align) throws DCEBufferException
827     {
828
829         // Read the string
830

831         String JavaDoc str = getCharArray();
832
833         // Align the read position
834

835         alignRxPosition(align);
836
837         // Return the string
838

839         return str;
840     }
841
842     /**
843      * Get a string from the buffer and align on the specified boundary
844      *
845      * @param align int
846      * @return String
847      * @exception DCEBufferException
848      */

849     public final String JavaDoc getString(int align) throws DCEBufferException
850     {
851
852         // Read the string
853

854         String JavaDoc str = getString();
855
856         // Align the read position
857

858         alignRxPosition(align);
859
860         // Return the string
861

862         return str;
863     }
864
865     /**
866      * Get a string from the buffer if the String variable is not null, and align on the specified
867      * boundary
868      *
869      * @param strVar String
870      * @param align int
871      * @return String
872      * @exception DCEBufferException
873      */

874     public final String JavaDoc getStringNotNull(String JavaDoc strVar, int align) throws DCEBufferException
875     {
876
877         // Check if the string variable is not null
878

879         String JavaDoc str = "";
880
881         if (strVar != null)
882         {
883
884             // Read the string
885

886             str = getString();
887
888             // Align the read position
889

890             alignRxPosition(align);
891         }
892
893         // Return the string
894

895         return str;
896     }
897
898     /**
899      * Get a string from a particular position in the buffer
900      *
901      * @param pos int
902      * @return String
903      * @exception DCEBufferException
904      */

905     public final String JavaDoc getStringAt(int pos) throws DCEBufferException
906     {
907
908         // Check if position is within the buffer
909

910         if (m_buffer.length < pos)
911             throw new DCEBufferException("Buffer offset out of range, " + pos);
912
913         // Unpack the string
914

915         String JavaDoc str = DataPacker.getUnicodeString(m_buffer, pos, MAX_STRING_LEN);
916         return str;
917     }
918
919     /**
920      * Read a Unicode string header and return the string length. -1 indicates a null pointer in the
921      * string header.
922      *
923      * @return int
924      * @exception DCEBufferException
925      */

926     public final int getUnicodeHeaderLength() throws DCEBufferException
927     {
928
929         // Check if there is enough data in the buffer for the Unicode header
930

931         if (m_buffer.length - m_rdpos < 8)
932             throw new DCEBufferException("End of DCE buffer");
933
934         // Get the string length
935

936         int len = (int) DataPacker.getIntelShort(m_buffer, m_rdpos);
937         m_rdpos += 4; // skip the max length too
938
int ptr = DataPacker.getIntelInt(m_buffer, m_rdpos);
939         m_rdpos += 4;
940
941         // Check if the pointer is valid
942

943         if (ptr == 0)
944             return -1;
945         return len;
946     }
947
948     /**
949      * Get a unicode string from the current position in the buffer
950      *
951      * @return String
952      * @exception DCEBufferException
953      */

954     public final String JavaDoc getUnicodeString() throws DCEBufferException
955     {
956
957         // Check if there is any buffer to read
958

959         if (m_buffer.length - m_rdpos <= 0)
960             throw new DCEBufferException("No more buffer");
961
962         // Unpack the string
963

964         String JavaDoc str = DataPacker.getUnicodeString(m_buffer, m_rdpos, MAX_STRING_LEN);
965         if (str != null)
966             m_rdpos += (str.length() * 2) + 2;
967         return str;
968     }
969
970     /**
971      * Get a data block from the buffer and align on the specified boundary
972      *
973      * @param align int
974      * @return byte[]
975      * @exception DCEBufferException
976      */

977     public final byte[] getDataBlock(int align) throws DCEBufferException
978     {
979
980         // Check if there is enough data in the buffer
981

982         if (m_buffer.length - m_rdpos < 12)
983             throw new DCEBufferException("End of DCE buffer");
984
985         // Unpack the data block
986

987         int len = getInt();
988         m_rdpos += 8; // skip undoc and max_len ints
989

990         // Copy the raw data block
991

992         byte[] dataBlk = null;
993
994         if (len > 0)
995         {
996
997             // Allocate the data block buffer
998

999             dataBlk = new byte[len];
1000
1001            // Copy the raw data
1002

1003            System.arraycopy(m_buffer, m_rdpos, dataBlk, 0, len);
1004        }
1005
1006        // Update the buffer position and align
1007

1008        m_rdpos += len;
1009        alignRxPosition(align);
1010        return dataBlk;
1011    }
1012
1013    /**
1014     * Get a UUID from the buffer
1015     *
1016     * @param readVer boolean
1017     * @return UUID
1018     * @exception DCEBufferException
1019     */

1020    public final UUID getUUID(boolean readVer) throws DCEBufferException
1021    {
1022
1023        // Check if there is enough data in the buffer
1024

1025        int len = UUID.UUID_LENGTH_BINARY;
1026        if (readVer == true)
1027            len += 4;
1028
1029        if (m_buffer.length - m_rdpos < len)
1030            throw new DCEBufferException("End of DCE buffer");
1031
1032        // Unpack the UUID
1033

1034        UUID uuid = new UUID(m_buffer, m_rdpos);
1035        m_rdpos += UUID.UUID_LENGTH_BINARY;
1036
1037        if (readVer == true)
1038        {
1039            int ver = getInt();
1040            uuid.setVersion(ver);
1041        }
1042
1043        return uuid;
1044    }
1045
1046    /**
1047     * Get an NT 64bit time value. If the value is valid then convert to a Java time value
1048     *
1049     * @return long
1050     * @throws DCEBufferException
1051     */

1052    public final long getNTTime() throws DCEBufferException
1053    {
1054
1055        // Get the raw NT time value
1056

1057        long ntTime = getLong();
1058        if (ntTime == 0 || ntTime == NTTime.InfiniteTime)
1059            return ntTime;
1060
1061        // Convert the time to a Java time value
1062

1063        return NTTime.toJavaDate(ntTime);
1064    }
1065
1066    /**
1067     * Get a byte structure that has a header
1068     *
1069     * @param buf byte[]
1070     * @throws DCEBufferException
1071     */

1072    public final byte[] getByteStructure(byte[] buf) throws DCEBufferException
1073    {
1074
1075        // Check if there is enough data in the buffer
1076

1077        if (m_buffer.length - m_rdpos < 12)
1078            throw new DCEBufferException("End of DCE buffer");
1079
1080        // Unpack the header
1081

1082        int maxLen = getInt();
1083        skipBytes(4); // offset
1084
int bytLen = getInt();
1085
1086        byte[] bytBuf = buf;
1087        if (bytBuf.length < bytLen)
1088            bytBuf = new byte[bytLen];
1089        return getBytes(bytBuf, bytLen);
1090    }
1091
1092    /**
1093     * Get a handle from the buffer
1094     *
1095     * @param handle PolicyHandle
1096     * @exception DCEBufferException
1097     */

1098    public final void getHandle(PolicyHandle handle) throws DCEBufferException
1099    {
1100
1101        // Check if there is enough data in the buffer
1102

1103        if (m_buffer.length - m_rdpos < PolicyHandle.POLICY_HANDLE_SIZE)
1104            throw new DCEBufferException("End of DCE buffer");
1105
1106        // Unpack the policy handle
1107

1108        m_rdpos = handle.loadPolicyHandle(m_buffer, m_rdpos);
1109    }
1110
1111    /**
1112     * Copy data from the DCE buffer to the user buffer, and update the current read position.
1113     *
1114     * @param buf byte[]
1115     * @param off int
1116     * @param cnt int
1117     * @return int
1118     * @exception DCEBufferException
1119     */

1120    public final int copyData(byte[] buf, int off, int cnt) throws DCEBufferException
1121    {
1122
1123        // Check if there is any more data to copy
1124

1125        if (m_rdpos == m_pos)
1126            return 0;
1127
1128        // Calculate the amount of data to copy
1129

1130        int siz = m_pos - m_rdpos;
1131        if (siz > cnt)
1132            siz = cnt;
1133
1134        // Copy the data to the user buffer and update the current read position
1135

1136        System.arraycopy(m_buffer, m_rdpos, buf, off, siz);
1137        m_rdpos += siz;
1138
1139        // Return the amount of data copied
1140

1141        return siz;
1142    }
1143
1144    /**
1145     * Append a raw data block to the buffer
1146     *
1147     * @param buf byte[]
1148     * @param off int
1149     * @param len int
1150     * @exception DCEBufferException
1151     */

1152    public final void appendData(byte[] buf, int off, int len) throws DCEBufferException
1153    {
1154
1155        // Check if there is enough space in the buffer
1156

1157        if (m_buffer.length - m_pos < len)
1158            extendBuffer(len);
1159
1160        // Copy the data to the buffer and update the current write position
1161

1162        System.arraycopy(buf, off, m_buffer, m_pos, len);
1163        m_pos += len;
1164    }
1165
1166    /**
1167     * Append an integer to the buffer
1168     *
1169     * @param ival int
1170     */

1171    public final void putInt(int ival)
1172    {
1173
1174        // Check if there is enough space in the buffer
1175

1176        if (m_buffer.length - m_pos < 4)
1177            extendBuffer();
1178
1179        // Pack the integer value
1180

1181        DataPacker.putIntelInt(ival, m_buffer, m_pos);
1182        m_pos += 4;
1183    }
1184
1185    /**
1186     * Append a byte value to the buffer
1187     *
1188     * @param bval int
1189     */

1190    public final void putByte(int bval)
1191    {
1192
1193        // Check if there is enough space in the buffer
1194

1195        if (m_buffer.length - m_pos < 1)
1196            extendBuffer();
1197
1198        // Pack the short value
1199

1200        m_buffer[m_pos++] = (byte) (bval & 0xFF);
1201    }
1202
1203    /**
1204     * Append a byte value to the buffer and align to the specified boundary
1205     *
1206     * @param bval byte
1207     * @param align int
1208     */

1209    public final void putByte(byte bval, int align)
1210    {
1211
1212        // Check if there is enough space in the buffer
1213

1214        if (m_buffer.length - m_pos < 1)
1215            extendBuffer();
1216
1217        // Pack the short value
1218

1219        m_buffer[m_pos++] = bval;
1220        alignPosition(align);
1221    }
1222
1223    /**
1224     * Append a byte value to the buffer and align to the specified boundary
1225     *
1226     * @param bval int
1227     * @param align int
1228     */

1229    public final void putByte(int bval, int align)
1230    {
1231
1232        // Check if there is enough space in the buffer
1233

1234        if (m_buffer.length - m_pos < 1)
1235            extendBuffer();
1236
1237        // Pack the short value
1238

1239        m_buffer[m_pos++] = (byte) (bval & 0xFF);
1240        alignPosition(align);
1241    }
1242
1243    /**
1244     * Append a block of bytes to the buffer
1245     *
1246     * @param bval byte[]
1247     * @param len int
1248     */

1249    public final void putBytes(byte[] bval, int len)
1250    {
1251
1252        // Check if there is enough space in the buffer
1253

1254        if (m_buffer.length - m_pos < len)
1255            extendBuffer();
1256
1257        // Pack the bytes
1258

1259        for (int i = 0; i < len; i++)
1260            m_buffer[m_pos++] = bval[i];
1261    }
1262
1263    /**
1264     * Append a block of bytes to the buffer
1265     *
1266     * @param bval byte[]
1267     * @param len int
1268     * @param align int
1269     */

1270    public final void putBytes(byte[] bval, int len, int align)
1271    {
1272
1273        // Check if there is enough space in the buffer
1274

1275        if (m_buffer.length - m_pos < len)
1276            extendBuffer();
1277
1278        // Pack the bytes
1279

1280        for (int i = 0; i < len; i++)
1281            m_buffer[m_pos++] = bval[i];
1282
1283        // Align the new buffer position
1284

1285        alignPosition(align);
1286    }
1287
1288    /**
1289     * Append a short value to the buffer
1290     *
1291     * @param sval int
1292     */

1293    public final void putShort(int sval)
1294    {
1295
1296        // Check if there is enough space in the buffer
1297

1298        if (m_buffer.length - m_pos < 2)
1299            extendBuffer();
1300
1301        // Pack the short value
1302

1303        DataPacker.putIntelShort(sval, m_buffer, m_pos);
1304        m_pos += 2;
1305    }
1306
1307    /**
1308     * Append a DCE string to the buffer
1309     *
1310     * @param str String
1311     */

1312    public final void putString(String JavaDoc str)
1313    {
1314
1315        // Check if there is enough space in the buffer
1316

1317        int reqLen = (str.length() * 2) + 24;
1318
1319        if (m_buffer.length - m_pos < reqLen)
1320            extendBuffer(reqLen);
1321
1322        // Pack the string
1323

1324        m_pos = DCEDataPacker.putDCEString(m_buffer, m_pos, str, false);
1325    }
1326
1327    /**
1328     * Append a DCE string to the buffer and align to the specified boundary
1329     *
1330     * @param str String
1331     * @param align int
1332     */

1333    public final void putString(String JavaDoc str, int align)
1334    {
1335
1336        // Check if there is enough space in the buffer
1337

1338        int reqLen = (str.length() * 2) + 24;
1339
1340        if (m_buffer.length - m_pos < reqLen)
1341            extendBuffer(reqLen);
1342
1343        // Pack the string
1344

1345        m_pos = DCEDataPacker.putDCEString(m_buffer, m_pos, str, false);
1346
1347        // Align the new buffer position
1348

1349        alignPosition(align);
1350    }
1351
1352    /**
1353     * Append a DCE string to the buffer, specify whether the nul is included in the string length
1354     * or not
1355     *
1356     * @param str String
1357     * @param align int
1358     * @param incNul boolean
1359     */

1360    public final void putString(String JavaDoc str, int align, boolean incNul)
1361    {
1362
1363        // Check if there is enough space in the buffer
1364

1365        int reqLen = (str.length() * 2) + 24;
1366        if (incNul)
1367            reqLen += 2;
1368
1369        if (m_buffer.length - m_pos < reqLen)
1370            extendBuffer(reqLen);
1371
1372        // Pack the string
1373

1374        m_pos = DCEDataPacker.putDCEString(m_buffer, m_pos, str, incNul);
1375
1376        // Align the new buffer position
1377

1378        alignPosition(align);
1379    }
1380
1381    /**
1382     * Append string return buffer details. Some DCE/RPC requests incorrectly send output parameters
1383     * as input.
1384     *
1385     * @param len int
1386     * @param align int
1387     */

1388    public final void putStringReturn(int len, int align)
1389    {
1390
1391        // Check if there is enough space in the buffer
1392

1393        if (m_buffer.length - m_pos < 20)
1394            extendBuffer();
1395
1396        // Pack the string return details
1397

1398        DataPacker.putIntelInt(len, m_buffer, m_pos);
1399        DataPacker.putZeros(m_buffer, m_pos + 4, 8);
1400        DataPacker.putIntelInt(DUMMY_ADDRESS, m_buffer, m_pos + 12);
1401        m_pos += 16;
1402
1403        // Align the new buffer position
1404

1405        alignPosition(align);
1406    }
1407
1408    /**
1409     * Append a DCE string header to the buffer
1410     *
1411     * @param str String
1412     * @param incNul boolean
1413     */

1414    public final void putUnicodeHeader(String JavaDoc str, boolean incNul)
1415    {
1416
1417        // Check if there is enough space in the buffer
1418

1419        if (m_buffer.length - m_pos < 8)
1420            extendBuffer();
1421
1422        // Calculate the string length in bytes
1423

1424        int sLen = 0;
1425        if (str != null)
1426            sLen = str.length() * 2;
1427
1428        // Pack the string header
1429

1430        if (str != null)
1431            DataPacker.putIntelShort(incNul ? sLen + 2 : sLen, m_buffer, m_pos);
1432        else
1433            DataPacker.putIntelShort(0, m_buffer, m_pos);
1434
1435        DataPacker.putIntelShort(sLen != 0 ? sLen + 2 : 0, m_buffer, m_pos + 2);
1436        DataPacker.putIntelInt(str != null ? DUMMY_ADDRESS : 0, m_buffer, m_pos + 4);
1437
1438        m_pos += 8;
1439    }
1440
1441    /**
1442     * Append a Unicode return string header to the buffer. Some DCE/RPC requests incorrectly send
1443     * output parameters as input.
1444     *
1445     * @param len int
1446     */

1447    public final void putUnicodeReturn(int len)
1448    {
1449
1450        // Check if there is enough space in the buffer
1451

1452        if (m_buffer.length - m_pos < 8)
1453            extendBuffer();
1454
1455        // Pack the string header
1456

1457        DataPacker.putIntelShort(0, m_buffer, m_pos);
1458        DataPacker.putIntelShort(len, m_buffer, m_pos + 2);
1459        DataPacker.putIntelInt(DUMMY_ADDRESS, m_buffer, m_pos + 4);
1460
1461        m_pos += 8;
1462    }
1463
1464    /**
1465     * Append a DCE string header to the buffer
1466     *
1467     * @param len int
1468     * @param incNul boolean
1469     */

1470    public final void putUnicodeHeader(int len)
1471    {
1472
1473        // Check if there is enough space in the buffer
1474

1475        if (m_buffer.length - m_pos < 8)
1476            extendBuffer();
1477
1478        // Calculate the string length in bytes
1479

1480        int sLen = len * 2;
1481
1482        // Pack the string header
1483

1484        DataPacker.putIntelShort(sLen, m_buffer, m_pos);
1485        DataPacker.putIntelShort(sLen + 2, m_buffer, m_pos + 2);
1486        DataPacker.putIntelInt(sLen != 0 ? DUMMY_ADDRESS : 0, m_buffer, m_pos + 4);
1487
1488        m_pos += 8;
1489    }
1490
1491    /**
1492     * Append an ASCII string to the DCE buffer
1493     *
1494     * @param str String
1495     * @param incNul boolean
1496     */

1497    public final void putASCIIString(String JavaDoc str, boolean incNul)
1498    {
1499
1500        // Check if there is enough space in the buffer
1501

1502        if (m_buffer.length - m_pos < (str.length() + 1))
1503            extendBuffer(str.length() + 2);
1504
1505        // Pack the string
1506

1507        m_pos = DataPacker.putString(str, m_buffer, m_pos, incNul);
1508    }
1509
1510    /**
1511     * Append an ASCII string to the DCE buffer, and align on the specified boundary
1512     *
1513     * @param str String
1514     * @param incNul boolean
1515     * @param align int
1516     */

1517    public final void putASCIIString(String JavaDoc str, boolean incNul, int align)
1518    {
1519
1520        // Check if there is enough space in the buffer
1521

1522        if (m_buffer.length - m_pos < (str.length() + 1))
1523            extendBuffer(str.length() + 8);
1524
1525        // Pack the string
1526

1527        m_pos = DataPacker.putString(str, m_buffer, m_pos, incNul);
1528
1529        // Align the buffer position
1530

1531        alignPosition(align);
1532    }
1533
1534    /**
1535     * Append a pointer to the buffer.
1536     *
1537     * @param obj Object
1538     */

1539    public final void putPointer(Object JavaDoc obj)
1540    {
1541
1542        // Check if there is enough space in the buffer
1543

1544        if (m_buffer.length - m_pos < 4)
1545            extendBuffer();
1546
1547        // Check if the object is valid, if not then put a null pointer into the buffer
1548

1549        if (obj == null)
1550            DataPacker.putZeros(m_buffer, m_pos, 4);
1551        else
1552            DataPacker.putIntelInt(DUMMY_ADDRESS, m_buffer, m_pos);
1553        m_pos += 4;
1554    }
1555
1556    /**
1557     * Append a pointer to the buffer.
1558     *
1559     * @param notNull boolean
1560     */

1561    public final void putPointer(boolean notNull)
1562    {
1563
1564        // Check if there is enough space in the buffer
1565

1566        if (m_buffer.length - m_pos < 4)
1567            extendBuffer();
1568
1569        // Check if the object is valid, if not then put a null pointer into the buffer
1570

1571        if (notNull == false)
1572            DataPacker.putZeros(m_buffer, m_pos, 4);
1573        else
1574            DataPacker.putIntelInt(DUMMY_ADDRESS, m_buffer, m_pos);
1575        m_pos += 4;
1576    }
1577
1578    /**
1579     * Append a UUID to the buffer
1580     *
1581     * @param uuid UUID
1582     * @param writeVer boolean
1583     */

1584    public final void putUUID(UUID uuid, boolean writeVer)
1585    {
1586
1587        // Check if there is enough space in the buffer
1588

1589        int len = UUID.UUID_LENGTH_BINARY;
1590        if (writeVer == true)
1591            len += 4;
1592
1593        if (m_buffer.length - m_pos < len)
1594            extendBuffer();
1595
1596        // Pack the UUID
1597

1598        m_pos = uuid.storeUUID(m_buffer, m_pos, writeVer);
1599    }
1600
1601    /**
1602     * Append a policy handle to the buffer
1603     *
1604     * @param handle PolicyHandle
1605     */

1606    public final void putHandle(PolicyHandle handle)
1607    {
1608
1609        // Check if there is enough space in the buffer
1610

1611        if (m_buffer.length - m_pos < PolicyHandle.POLICY_HANDLE_SIZE)
1612            extendBuffer(PolicyHandle.POLICY_HANDLE_SIZE);
1613
1614        // Pack the policy handle
1615

1616        m_pos = handle.storePolicyHandle(m_buffer, m_pos);
1617    }
1618
1619    /**
1620     * Append a DCE buffer to the current DCE buffer
1621     *
1622     * @param buf DCEBuffer
1623     */

1624    public final void putBuffer(DCEBuffer buf)
1625    {
1626        try
1627        {
1628            appendData(buf.getBuffer(), buf.getReadPosition(), buf.getLength());
1629        }
1630        catch (DCEBufferException ex)
1631        {
1632        }
1633    }
1634
1635    /**
1636     * Append an error status to the buffer, also sets the error status value
1637     *
1638     * @param sts int
1639     */

1640    public final void putErrorStatus(int sts)
1641    {
1642
1643        // Check if there is enough space in the buffer
1644

1645        if (m_buffer.length - m_pos < 4)
1646            extendBuffer();
1647
1648        // Pack the status value
1649

1650        DataPacker.putIntelInt(sts, m_buffer, m_pos);
1651        m_pos += 4;
1652
1653        // Save the status value
1654

1655        m_errorCode = sts;
1656    }
1657
1658    /**
1659     * Append a DCE header to the buffer
1660     *
1661     * @param pdutyp int
1662     * @param callid int
1663     */

1664    public final void putHeader(int pdutyp, int callid)
1665    {
1666        m_buffer[m_pos++] = VAL_VERSIONMAJOR;
1667        m_buffer[m_pos++] = VAL_VERSIONMINOR;
1668        m_buffer[m_pos++] = (byte) (pdutyp & 0xFF);
1669        m_buffer[m_pos++] = 0;
1670
1671        DataPacker.putIntelInt(VAL_PACKEDDATAREP, m_buffer, m_pos);
1672        m_pos += 4;
1673
1674        DataPacker.putZeros(m_buffer, m_pos, 4);
1675        m_pos += 4;
1676
1677        DataPacker.putIntelInt(callid, m_buffer, m_pos);
1678        m_pos += 4;
1679    }
1680
1681    /**
1682     * Append a bind header to the buffer
1683     *
1684     * @param callid int
1685     */

1686    public final void putBindHeader(int callid)
1687    {
1688        putHeader(DCECommand.BIND, callid);
1689    }
1690
1691    /**
1692     * Append a bind acknowlegde header to the buffer
1693     *
1694     * @param callid int
1695     */

1696    public final void putBindAckHeader(int callid)
1697    {
1698        putHeader(DCECommand.BINDACK, callid);
1699    }
1700
1701    /**
1702     * Append a request header to the buffer
1703     *
1704     * @param callid int
1705     * @param opcode int
1706     * @param allocHint int
1707     */

1708    public final void putRequestHeader(int callid, int opcode, int allocHint)
1709    {
1710        putHeader(DCECommand.REQUEST, callid);
1711        DataPacker.putIntelInt(allocHint, m_buffer, m_pos);
1712        m_pos += 4;
1713        DataPacker.putZeros(m_buffer, m_pos, 2);
1714        m_pos += 2;
1715        DataPacker.putIntelShort(opcode, m_buffer, m_pos);
1716        m_pos += 2;
1717    }
1718
1719    /**
1720     * Append a response header to the buffer
1721     *
1722     * @param callid int
1723     * @param allocHint int
1724     */

1725    public final void putResponseHeader(int callid, int allocHint)
1726    {
1727        putHeader(DCECommand.RESPONSE, callid);
1728        DataPacker.putIntelInt(allocHint, m_buffer, m_pos);
1729        m_pos += 4;
1730        DataPacker.putZeros(m_buffer, m_pos, 4);
1731        m_pos += 4;
1732    }
1733
1734    /**
1735     * Append zero integers to the buffer
1736     *
1737     * @param cnt int
1738     */

1739    public final void putZeroInts(int cnt)
1740    {
1741
1742        // Check if there is enough space in the buffer
1743

1744        int bytCnt = cnt * 4;
1745        if (m_buffer.length - m_pos < bytCnt)
1746            extendBuffer(bytCnt * 2);
1747
1748        // Pack the zero integer values
1749

1750        DataPacker.putZeros(m_buffer, m_pos, bytCnt);
1751        m_pos += bytCnt;
1752    }
1753
1754    /**
1755     * Reset the buffer pointers to reuse the buffer
1756     */

1757    public final void resetBuffer()
1758    {
1759
1760        // Reset the read/write positions
1761

1762        m_pos = 0;
1763        m_rdpos = 0;
1764
1765        // If the buffer is over sized release it and allocate a standard sized buffer
1766

1767        if (m_buffer.length >= MAX_BUFFER_SIZE)
1768            m_buffer = new byte[DEFAULT_BUFSIZE];
1769    }
1770
1771    /**
1772     * Set the new write position
1773     *
1774     * @param pos int
1775     */

1776    public final void setWritePosition(int pos)
1777    {
1778        m_pos = pos;
1779    }
1780
1781    /**
1782     * Update the write position by the specified amount
1783     *
1784     * @param len int
1785     */

1786    public final void updateWritePosition(int len)
1787    {
1788        m_pos += len;
1789    }
1790
1791    /**
1792     * Determine if there is an error status set
1793     *
1794     * @return boolean
1795     */

1796    public final boolean hasErrorStatus()
1797    {
1798        return m_errorCode != 0 ? true : false;
1799    }
1800
1801    /**
1802     * Return the error status code
1803     *
1804     * @return int
1805     */

1806    public final int getErrorStatus()
1807    {
1808        return m_errorCode;
1809    }
1810
1811    /**
1812     * Set the error status code
1813     *
1814     * @param sts int
1815     */

1816    public final void setErrorStatus(int sts)
1817    {
1818        m_errorCode = sts;
1819    }
1820
1821    /**
1822     * Extend the DCE buffer by the specified amount
1823     *
1824     * @param ext int
1825     */

1826    private final void extendBuffer(int ext)
1827    {
1828
1829        // Create a new buffer of the required size
1830

1831        byte[] newBuf = new byte[m_buffer.length + ext];
1832
1833        // Copy the data from the current buffer to the new buffer
1834

1835        System.arraycopy(m_buffer, 0, newBuf, 0, m_buffer.length);
1836
1837        // Set the new buffer to be the main buffer
1838

1839        m_buffer = newBuf;
1840    }
1841
1842    /**
1843     * Extend the DCE buffer, double the currently allocated buffer size
1844     */

1845    private final void extendBuffer()
1846    {
1847        extendBuffer(m_buffer.length * 2);
1848    }
1849
1850    /**
1851     * Align the current buffer position on the specified boundary
1852     *
1853     * @param align int
1854     */

1855    private final void alignPosition(int align)
1856    {
1857
1858        // Range check the alignment
1859

1860        if (align < 0 || align > 2)
1861            return;
1862
1863        // Align the buffer position on the required boundary
1864

1865        m_pos = (m_pos + _alignRound[align]) & _alignMask[align];
1866    }
1867
1868    /**
1869     * Align the receive buffer position on the specified boundary
1870     *
1871     * @param align int
1872     */

1873    private final void alignRxPosition(int align)
1874    {
1875
1876        // Range check the alignment
1877

1878        if (align < 0 || align > 2 || m_rdpos >= m_buffer.length)
1879            return;
1880
1881        // Align the buffer position on the required boundary
1882

1883        m_rdpos = (m_rdpos + _alignRound[align]) & _alignMask[align];
1884    }
1885
1886    /**
1887     * Dump the DCE buffered data
1888     */

1889    public final void Dump()
1890    {
1891        int len = getLength();
1892        if (len == 0)
1893            len = 24;
1894        HexDump.Dump(getBuffer(), len, m_base);
1895    }
1896}
1897
Popular Tags