Initial commit.
[pdfium.git] / fpdfsdk / src / javascript / JS_GlobalData.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../include/javascript/JavaScript.h"\r
8 #include "../../include/javascript/IJavaScript.h"\r
9 #include "../../include/javascript/JS_GlobalData.h"\r
10 \r
11 #define JS_MAXGLOBALDATA                        (1024 * 4 - 8)\r
12 \r
13 /* --------------------- CJS_GlobalVariableArray --------------------- */\r
14 \r
15 CJS_GlobalVariableArray::CJS_GlobalVariableArray()\r
16 {\r
17 }\r
18 \r
19 CJS_GlobalVariableArray::~CJS_GlobalVariableArray()\r
20 {\r
21         Empty();\r
22 }\r
23 \r
24 void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array)\r
25 {\r
26         Empty();\r
27         for (int i=0,sz=array.Count(); i<sz; i++)\r
28         {\r
29                 CJS_KeyValue* pOldObjData = array.GetAt(i);\r
30                 ASSERT(pOldObjData != NULL);\r
31 \r
32                 switch (pOldObjData->nType)\r
33                 {\r
34                 case JS_GLOBALDATA_TYPE_NUMBER:\r
35                         {\r
36                                 CJS_KeyValue* pNewObjData = new CJS_KeyValue;\r
37                                 pNewObjData->sKey = pOldObjData->sKey;\r
38                                 pNewObjData->nType = pOldObjData->nType;\r
39                                 pNewObjData->dData = pOldObjData->dData;\r
40                                 Add(pNewObjData);\r
41                         }\r
42                         break;\r
43                 case JS_GLOBALDATA_TYPE_BOOLEAN:\r
44                         {\r
45                                 CJS_KeyValue* pNewObjData = new CJS_KeyValue;\r
46                                 pNewObjData->sKey = pOldObjData->sKey;\r
47                                 pNewObjData->nType = pOldObjData->nType;\r
48                                 pNewObjData->bData = pOldObjData->bData;\r
49                                 Add(pNewObjData);\r
50                         }\r
51                         break;\r
52                 case JS_GLOBALDATA_TYPE_STRING:\r
53                         {\r
54                                 CJS_KeyValue* pNewObjData = new CJS_KeyValue;\r
55                                 pNewObjData->sKey = pOldObjData->sKey;\r
56                                 pNewObjData->nType = pOldObjData->nType;\r
57                                 pNewObjData->sData = pOldObjData->sData;\r
58                                 Add(pNewObjData);\r
59                         }\r
60                         break;\r
61                 case JS_GLOBALDATA_TYPE_OBJECT:\r
62                         {\r
63                                 CJS_KeyValue* pNewObjData = new CJS_KeyValue;\r
64                                 pNewObjData->sKey = pOldObjData->sKey;\r
65                                 pNewObjData->nType = pOldObjData->nType;\r
66                                 pNewObjData->objData.Copy(pOldObjData->objData);\r
67                                 Add(pNewObjData);\r
68                         }\r
69                 case JS_GLOBALDATA_TYPE_NULL:\r
70                         {\r
71                                 CJS_KeyValue* pNewObjData = new CJS_KeyValue;\r
72                                 pNewObjData->sKey = pOldObjData->sKey;\r
73                                 pNewObjData->nType = pOldObjData->nType;\r
74                                 Add(pNewObjData);\r
75                         }\r
76                 }\r
77         }\r
78 }\r
79 \r
80 void CJS_GlobalVariableArray::Add(CJS_KeyValue* p)\r
81 {\r
82         array.Add(p);\r
83 }\r
84 \r
85 int CJS_GlobalVariableArray::Count() const\r
86 {\r
87         return array.GetSize();\r
88 }\r
89 \r
90 CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const\r
91 {\r
92         return array.GetAt(index);\r
93 }\r
94 \r
95 void CJS_GlobalVariableArray::Empty()\r
96 {\r
97         for (int i=0,sz=array.GetSize(); i<sz; i++)\r
98                 delete array.GetAt(i);\r
99         array.RemoveAll();\r
100 }\r
101 \r
102 /* -------------------------- CJS_GlobalData -------------------------- */\r
103 \r
104 #define READER_JS_GLOBALDATA_FILENAME                           L"Reader_JsGlobal.Data"\r
105 #define PHANTOM_JS_GLOBALDATA_FILENAME                          L"Phantom_JsGlobal.Data"\r
106 #define SDK_JS_GLOBALDATA_FILENAME                                      L"SDK_JsGlobal.Data"\r
107 \r
108 static const FX_BYTE JS_RC4KEY[] = {0x19,0xa8,0xe8,0x01,0xf6,0xa8,0xb6,0x4d,0x82,0x04,\r
109                                                         0x45,0x6d,0xb4,0xcf,0xd7,0x77,0x67,0xf9,0x75,0x9f,\r
110                                                         0xf0,0xe0,0x1e,0x51,0xee,0x46,0xfd,0x0b,0xc9,0x93,\r
111                                                         0x25,0x55,0x4a,0xee,0xe0,0x16,0xd0,0xdf,0x8c,0xfa,\r
112                                                         0x2a,0xa9,0x49,0xfd,0x97,0x1c,0x0e,0x22,0x13,0x28,\r
113                                                         0x7c,0xaf,0xc4,0xfc,0x9c,0x12,0x65,0x8c,0x4e,0x5b,\r
114                                                         0x04,0x75,0x89,0xc9,0xb1,0xed,0x50,0xca,0x96,0x6f,\r
115                                                         0x1a,0x7a,0xfe,0x58,0x5d,0xec,0x19,0x4a,0xf6,0x35,\r
116                                                         0x6a,0x97,0x14,0x00,0x0e,0xd0,0x6b,0xbb,0xd5,0x75,\r
117                                                         0x55,0x8b,0x6e,0x6b,0x19,0xa0,0xf8,0x77,0xd5,0xa3\r
118                                                         };\r
119 \r
120 CJS_GlobalData::CJS_GlobalData(CPDFDoc_Environment* pApp) : m_pApp(pApp)\r
121 {\r
122 //      IBaseAnnot* pBaseAnnot = IBaseAnnot::GetBaseAnnot(m_pApp);\r
123 //      ASSERT(pBaseAnnot != NULL);\r
124 // \r
125 //      m_sFilePath = pBaseAnnot->GetUserPath();\r
126         m_sFilePath += SDK_JS_GLOBALDATA_FILENAME;\r
127 \r
128         LoadGlobalPersistentVariables();\r
129 }\r
130 \r
131 CJS_GlobalData::~CJS_GlobalData()\r
132 {\r
133         SaveGlobalPersisitentVariables();\r
134 \r
135         for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)\r
136                 delete m_arrayGlobalData.GetAt(i);\r
137 \r
138         m_arrayGlobalData.RemoveAll();\r
139 }\r
140 \r
141 int     CJS_GlobalData::FindGlobalVariable(FX_LPCSTR propname)\r
142 {\r
143         ASSERT(propname != NULL);\r
144 \r
145         int nRet = -1;\r
146 \r
147         for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)\r
148         {\r
149                 CJS_GlobalData_Element* pTemp = m_arrayGlobalData.GetAt(i);\r
150                 if (pTemp->data.sKey[0] == *propname && pTemp->data.sKey == propname)\r
151                 {\r
152                         nRet = i;\r
153                         break;\r
154                 }\r
155         }\r
156 \r
157         return nRet;\r
158 }\r
159 \r
160 CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(FX_LPCSTR propname)\r
161 {\r
162         ASSERT(propname != NULL);\r
163 \r
164         int     nFind = FindGlobalVariable(propname);\r
165 \r
166         if (nFind >= 0)\r
167                 return m_arrayGlobalData.GetAt(nFind);\r
168         else\r
169                 return NULL;\r
170 }\r
171 \r
172 void CJS_GlobalData::SetGlobalVariableNumber(FX_LPCSTR propname, double dData)\r
173 {\r
174         ASSERT(propname != NULL);\r
175         CFX_ByteString sPropName = propname;\r
176 \r
177         sPropName.TrimLeft();\r
178         sPropName.TrimRight();\r
179 \r
180         if (sPropName.GetLength() == 0) return;\r
181 \r
182         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
183         {\r
184                 pData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;\r
185                 pData->data.dData = dData;\r
186         }\r
187         else\r
188         {\r
189                 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;\r
190                 pNewData->data.sKey = sPropName;\r
191                 pNewData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;\r
192                 pNewData->data.dData = dData;\r
193 \r
194                 m_arrayGlobalData.Add(pNewData);\r
195         }\r
196 }\r
197 \r
198 void CJS_GlobalData::SetGlobalVariableBoolean(FX_LPCSTR propname, bool bData)\r
199 {\r
200         ASSERT(propname != NULL);\r
201         CFX_ByteString sPropName = propname;\r
202 \r
203         sPropName.TrimLeft();\r
204         sPropName.TrimRight();\r
205 \r
206         if (sPropName.GetLength() == 0) return;\r
207 \r
208         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
209         {\r
210                 pData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;\r
211                 pData->data.bData = bData;\r
212         }\r
213         else\r
214         {\r
215                 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;\r
216                 pNewData->data.sKey = sPropName;\r
217                 pNewData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;\r
218                 pNewData->data.bData = bData;\r
219 \r
220                 m_arrayGlobalData.Add(pNewData);\r
221         }\r
222 }\r
223 \r
224 void CJS_GlobalData::SetGlobalVariableString(FX_LPCSTR propname, const CFX_ByteString& sData)\r
225 {\r
226         ASSERT(propname != NULL);\r
227         CFX_ByteString sPropName = propname;\r
228 \r
229         sPropName.TrimLeft();\r
230         sPropName.TrimRight();\r
231 \r
232         if (sPropName.GetLength() == 0) return;\r
233 \r
234         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
235         {\r
236                 pData->data.nType = JS_GLOBALDATA_TYPE_STRING;\r
237                 pData->data.sData = sData;\r
238         }\r
239         else\r
240         {\r
241                 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;\r
242                 pNewData->data.sKey = sPropName;\r
243                 pNewData->data.nType = JS_GLOBALDATA_TYPE_STRING;\r
244                 pNewData->data.sData = sData;\r
245 \r
246                 m_arrayGlobalData.Add(pNewData);\r
247         }\r
248 }\r
249 \r
250 void CJS_GlobalData::SetGlobalVariableObject(FX_LPCSTR propname, const CJS_GlobalVariableArray& array)\r
251 {\r
252         ASSERT(propname != NULL);\r
253         CFX_ByteString sPropName = propname;\r
254 \r
255         sPropName.TrimLeft();\r
256         sPropName.TrimRight();\r
257 \r
258         if (sPropName.GetLength() == 0) return;\r
259 \r
260         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
261         {\r
262                 pData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;\r
263                 pData->data.objData.Copy(array);\r
264         }\r
265         else\r
266         {\r
267                 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;\r
268                 pNewData->data.sKey = sPropName;\r
269                 pNewData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;\r
270                 pNewData->data.objData.Copy(array);\r
271                 \r
272                 m_arrayGlobalData.Add(pNewData);\r
273         }\r
274 }\r
275 \r
276 void CJS_GlobalData::SetGlobalVariableNull(FX_LPCSTR propname)\r
277 {\r
278         ASSERT(propname != NULL);\r
279         CFX_ByteString sPropName = propname;\r
280         \r
281         sPropName.TrimLeft();\r
282         sPropName.TrimRight();\r
283         \r
284         if (sPropName.GetLength() == 0) return;\r
285         \r
286         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
287         {\r
288                 pData->data.nType = JS_GLOBALDATA_TYPE_NULL;\r
289         }\r
290         else\r
291         {\r
292                 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;\r
293                 pNewData->data.sKey = sPropName;\r
294                 pNewData->data.nType = JS_GLOBALDATA_TYPE_NULL;\r
295                 \r
296                 m_arrayGlobalData.Add(pNewData);\r
297         }\r
298 }\r
299 \r
300 FX_BOOL CJS_GlobalData::SetGlobalVariablePersistent(FX_LPCSTR propname, FX_BOOL bPersistent)\r
301 {\r
302         ASSERT(propname != NULL);\r
303         CFX_ByteString sPropName = propname;\r
304 \r
305         sPropName.TrimLeft();\r
306         sPropName.TrimRight();\r
307 \r
308         if (sPropName.GetLength() == 0) return FALSE;\r
309 \r
310         if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))\r
311         {\r
312                 pData->bPersistent = bPersistent;\r
313                 return TRUE;\r
314         }\r
315 \r
316         return FALSE;\r
317 }\r
318 \r
319 FX_BOOL CJS_GlobalData::DeleteGlobalVariable(FX_LPCSTR propname)\r
320 {\r
321         ASSERT(propname != NULL);\r
322         CFX_ByteString sPropName = propname;\r
323 \r
324         sPropName.TrimLeft();\r
325         sPropName.TrimRight();\r
326 \r
327         if (sPropName.GetLength() == 0) return FALSE;\r
328 \r
329         int     nFind = FindGlobalVariable(sPropName);\r
330 \r
331         if (nFind >= 0)\r
332         {\r
333                 delete m_arrayGlobalData.GetAt(nFind);\r
334                 m_arrayGlobalData.RemoveAt(nFind);\r
335                 return TRUE;\r
336         }\r
337 \r
338         return FALSE;\r
339 }\r
340 \r
341 FX_INT32 CJS_GlobalData::GetSize() const\r
342 {\r
343         return m_arrayGlobalData.GetSize();\r
344 }\r
345 \r
346 CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const\r
347 {\r
348         return m_arrayGlobalData.GetAt(index);\r
349 }\r
350 \r
351 void CJS_GlobalData::LoadGlobalPersistentVariables()\r
352 {\r
353         FX_LPBYTE pBuffer = NULL;\r
354         FX_INT32 nLength = 0;\r
355 \r
356         LoadFileBuffer(m_sFilePath, pBuffer, nLength);\r
357 \r
358         CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY));\r
359 \r
360         if (pBuffer)\r
361         {\r
362                 FX_LPBYTE p = pBuffer;\r
363                 FX_WORD wType = *((FX_WORD*)p);\r
364                 p += sizeof(FX_WORD);\r
365 \r
366                 //FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F');\r
367 \r
368                 if (wType == (FX_WORD)(('X' << 8) | 'F'))\r
369                 {\r
370                         FX_WORD wVersion = *((FX_WORD*)p);\r
371                         p += sizeof(FX_WORD);\r
372 \r
373                         ASSERT(wVersion <= 2);\r
374 \r
375                         FX_DWORD dwCount = *((FX_DWORD*)p);\r
376                         p += sizeof(FX_DWORD);\r
377 \r
378                         FX_DWORD dwSize = *((FX_DWORD*)p);\r
379                         p += sizeof(FX_DWORD);\r
380 \r
381                         if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_DWORD)* 2)\r
382                         {\r
383                                 for (FX_INT32 i=0,sz=dwCount; i<sz; i++)\r
384                                 {\r
385                                         if (p > pBuffer + nLength)\r
386                                                 break;\r
387 \r
388                                         FX_DWORD dwNameLen = *((FX_DWORD*)p);\r
389                                         p += sizeof(FX_DWORD);\r
390 \r
391                                         if (p + dwNameLen > pBuffer + nLength)\r
392                                                 break;\r
393 \r
394                                         CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen);\r
395                                         p += sizeof(char) * dwNameLen;\r
396 \r
397                                         FX_WORD wDataType = *((FX_WORD*)p);\r
398                                         p += sizeof(FX_WORD);\r
399 \r
400                                         switch (wDataType)\r
401                                         {\r
402                                         case JS_GLOBALDATA_TYPE_NUMBER:\r
403                                                 {\r
404                                                         double dData = 0;\r
405                                                         switch (wVersion)\r
406                                                         {\r
407                                                         case 1:\r
408                                                                 {\r
409                                                                         FX_DWORD dwData = *((FX_DWORD*)p);\r
410                                                                         p += sizeof(FX_DWORD);\r
411                                                                         dData = dwData;\r
412                                                                 }\r
413                                                                 break;\r
414                                                         case 2:\r
415                                                                 {\r
416                                                                         dData = *((double*)p);\r
417                                                                         p += sizeof(double);\r
418                                                                 }\r
419                                                                 break;\r
420                                                         }\r
421                                                         SetGlobalVariableNumber(sEntry, dData);\r
422                                                         SetGlobalVariablePersistent(sEntry, TRUE);\r
423                                                 }\r
424                                                 break;\r
425                                         case JS_GLOBALDATA_TYPE_BOOLEAN:\r
426                                                 {\r
427                                                         FX_WORD wData = *((FX_WORD*)p);\r
428                                                         p += sizeof(FX_WORD);\r
429                                                         SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));\r
430                                                         SetGlobalVariablePersistent(sEntry, TRUE);\r
431                                                 }\r
432                                                 break;\r
433                                         case JS_GLOBALDATA_TYPE_STRING:\r
434                                                 {\r
435                                                         FX_DWORD dwLength = *((FX_DWORD*)p);\r
436                                                         p += sizeof(FX_DWORD);\r
437 \r
438                                                         if (p + dwLength > pBuffer + nLength)\r
439                                                                 break;\r
440 \r
441                                                         SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength));\r
442                                                         SetGlobalVariablePersistent(sEntry, TRUE);\r
443                                                         p += sizeof(char) * dwLength;\r
444                                                 }\r
445                                                 break;\r
446                                         case JS_GLOBALDATA_TYPE_NULL:\r
447                                                 {\r
448                                                         SetGlobalVariableNull(sEntry);\r
449                                                         SetGlobalVariablePersistent(sEntry, TRUE);\r
450                                                 }\r
451                                         }\r
452                                 }\r
453                         }\r
454                 }\r
455                 FX_Free(pBuffer);\r
456         }\r
457 }\r
458 \r
459 /*\r
460 struct js_global_datafile_header\r
461 {\r
462         FX_WORD type; //FX ('X' << 8) | 'F'\r
463         FX_WORD version; //1.0\r
464         FX_DWORD datacount;\r
465 };\r
466 struct js_global_datafile_data\r
467 {\r
468         FX_WORD type;\r
469         FX_DWORD nData;\r
470         FX_WORD bData;\r
471         FX_DWORD nStrLen;\r
472         char* pStr;\r
473 };\r
474 */\r
475 \r
476 void CJS_GlobalData::SaveGlobalPersisitentVariables()\r
477 {\r
478         FX_DWORD nCount = 0;\r
479         CFX_BinaryBuf sData;\r
480 \r
481         for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)\r
482         {\r
483                 CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i);\r
484                 ASSERT(pElement != NULL);\r
485 \r
486                 if (pElement->bPersistent)\r
487                 {\r
488                         CFX_BinaryBuf sElement;\r
489                         MakeByteString(pElement->data.sKey, &pElement->data, sElement);\r
490 \r
491                         if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA)\r
492                                 break;\r
493 \r
494                         sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize());\r
495                         nCount++;\r
496                 }\r
497         }\r
498 \r
499         CFX_BinaryBuf sFile;\r
500 \r
501         FX_WORD wType = (FX_WORD)(('X' << 8) | 'F');\r
502         sFile.AppendBlock(&wType, sizeof(FX_WORD));\r
503         FX_WORD wVersion = 2;\r
504         sFile.AppendBlock(&wVersion, sizeof(FX_WORD));\r
505         sFile.AppendBlock(&nCount, sizeof(FX_DWORD));\r
506         FX_DWORD dwSize = sData.GetSize();\r
507         sFile.AppendBlock(&dwSize, sizeof(FX_DWORD));\r
508 \r
509         sFile.AppendBlock(sData.GetBuffer(), sData.GetSize());\r
510 \r
511         CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, sizeof(JS_RC4KEY));\r
512         WriteFileBuffer(m_sFilePath, (FX_LPCSTR)sFile.GetBuffer(), sFile.GetSize());\r
513 }\r
514 \r
515 void CJS_GlobalData::LoadFileBuffer(FX_LPCWSTR sFilePath, FX_LPBYTE& pBuffer, FX_INT32& nLength)\r
516 {\r
517 //UnSupport.\r
518 }\r
519 \r
520 void CJS_GlobalData::WriteFileBuffer(FX_LPCWSTR sFilePath, FX_LPCSTR pBuffer, FX_INT32 nLength)\r
521 {\r
522 //UnSupport.\r
523 }\r
524 \r
525 void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pData, CFX_BinaryBuf& sData)\r
526 {\r
527         ASSERT(pData != NULL);\r
528 \r
529         FX_WORD wType = (FX_WORD)pData->nType;\r
530 \r
531         switch (wType)\r
532         {\r
533         case JS_GLOBALDATA_TYPE_NUMBER:\r
534                 {\r
535                         FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();\r
536                         sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));\r
537                         sData.AppendString(name);\r
538 \r
539                         sData.AppendBlock(&wType, sizeof(FX_WORD));\r
540                         double dData = pData->dData;\r
541                         sData.AppendBlock(&dData, sizeof(double));\r
542                 }\r
543                 break;\r
544         case JS_GLOBALDATA_TYPE_BOOLEAN:\r
545                 {\r
546                         FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();\r
547                         sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));\r
548                         sData.AppendString(name);\r
549 \r
550                         sData.AppendBlock(&wType, sizeof(FX_WORD));\r
551                         FX_WORD wData = (FX_WORD)pData->bData;\r
552                         sData.AppendBlock(&wData, sizeof(FX_WORD));\r
553                 }\r
554                 break;\r
555         case JS_GLOBALDATA_TYPE_STRING:\r
556                 {\r
557                         FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();\r
558                         sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));\r
559                         sData.AppendString(name);\r
560 \r
561                         sData.AppendBlock(&wType, sizeof(FX_WORD));\r
562 \r
563                         FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength();\r
564                         sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD));\r
565                         sData.AppendString(pData->sData);\r
566                 }\r
567                 break;\r
568         case JS_GLOBALDATA_TYPE_NULL:\r
569                 {\r
570                         FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();\r
571                         sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));\r
572                         sData.AppendString(name);\r
573 \r
574                         sData.AppendBlock(&wType, sizeof(FX_DWORD));\r
575                 }\r
576                 break;\r
577         default:\r
578                 break;\r
579         }\r
580 }\r
581 \r