Merge pull request #4676 from jmarshallnz/dont_set_scraper_on_tvshow_on_nfo
[vuplus_xbmc] / xbmc / utils / WindowsShortcut.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 // WindowsShortcut.cpp: implementation of the CWindowsShortcut class.
22 //
23 //////////////////////////////////////////////////////////////////////
24
25 #include "sc.h"
26 #include "WindowsShortcut.h"
27
28 #ifdef _DEBUG
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #define new DEBUG_NEW
32 #endif
33
34
35 #define FLAG_SHELLITEMIDLIST   1
36 #define FLAG_FILEORDIRECTORY   2
37 #define FLAG_DESCRIPTION     4
38 #define FLAG_RELATIVEPATH     8
39 #define FLAG_WORKINGDIRECTORY   0x10
40 #define FLAG_ARGUMENTS          0x20
41 #define FLAG_ICON               0x40
42
43 #define VOLUME_LOCAL        1
44 #define VOLUME_NETWORK      2
45 //////////////////////////////////////////////////////////////////////
46 // Construction/Destruction
47 //////////////////////////////////////////////////////////////////////
48
49 CWindowsShortcut::CWindowsShortcut()
50 {
51 }
52
53 CWindowsShortcut::~CWindowsShortcut()
54 {
55 }
56
57 bool CWindowsShortcut::GetShortcut(const string& strFileName, string& strFileOrDir)
58 {
59   strFileOrDir = "";
60   if (!IsShortcut(strFileName) ) return false;
61
62
63   CFile file;
64   if (!file.Open(strFileName.c_str(), CFile::typeBinary | CFile::modeRead)) return false;
65   byte byHeader[2048];
66   int iBytesRead = file.Read(byHeader, 2048);
67   file.Close();
68
69   DWORD dwFlags = *((DWORD*)(&byHeader[0x14]));
70
71   int iPos = 0x4c;
72   if (dwFlags & FLAG_SHELLITEMIDLIST)
73   {
74     WORD sLength = *((WORD*)(&byHeader[iPos]));
75     iPos += sLength;
76     iPos += 2;
77   }
78
79   // skip File Location Info
80   DWORD dwLen = 0x1c;
81   if (dwFlags & FLAG_SHELLITEMIDLIST)
82   {
83     dwLen = *((DWORD*)(&byHeader[iPos]));
84   }
85
86
87   DWORD dwVolumeFlags = *((DWORD*)(&byHeader[iPos + 0x8]));
88   DWORD dwOffsetLocalVolumeInfo = *((DWORD*)(&byHeader[iPos + 0xc]));
89   DWORD dwOffsetBasePathName = *((DWORD*)(&byHeader[iPos + 0x10]));
90   DWORD dwOffsetNetworkVolumeInfo = *((DWORD*)(&byHeader[iPos + 0x14]));
91   DWORD dwOffsetRemainingPathName = *((DWORD*)(&byHeader[iPos + 0x18]));
92
93
94   if ((dwVolumeFlags & VOLUME_NETWORK) == 0) return false;
95
96   strFileOrDir = "smb:";
97   // share name
98   iPos += dwOffsetNetworkVolumeInfo + 0x14;
99   while (byHeader[iPos] != 0 && iPos < iBytesRead)
100   {
101     if (byHeader[iPos] == '\\') byHeader[iPos] = '/';
102     strFileOrDir += (char)byHeader[iPos];
103     iPos++;
104   }
105   iPos++;
106   // file/folder name
107   strFileOrDir += '/';
108   while (byHeader[iPos] != 0 && iPos < iBytesRead)
109   {
110     if (byHeader[iPos] == '\\') byHeader[iPos] = '/';
111     strFileOrDir += (char)byHeader[iPos];
112     iPos++;
113   }
114   return true;
115 }
116
117 bool CWindowsShortcut::IsShortcut(const string& strFileName)
118 {
119   CFile file;
120   if (!file.Open(strFileName.c_str(), CFile::typeBinary | CFile::modeRead)) return false;
121   byte byHeader[0x80];
122   int iBytesRead = file.Read(byHeader, 0x80);
123   file.Close();
124   if (iBytesRead < 0x4c)
125   {
126     return false;
127   }
128   //long integer that is always set to 4Ch
129   if (byHeader[0] != 0x4c) return false;
130   if (byHeader[1] != 0x0 ) return false;
131   if (byHeader[2] != 0x0 ) return false;
132   if (byHeader[3] != 0x0 ) return false;
133
134   //globally unique identifier GUID of the shell links
135   if (byHeader[0x04] != 0x01) return false;
136   if (byHeader[0x05] != 0x14) return false;
137   if (byHeader[0x06] != 0x02) return false;
138   if (byHeader[0x07] != 0x00) return false;
139   if (byHeader[0x08] != 0x00) return false;
140   if (byHeader[0x09] != 0x00) return false;
141   if (byHeader[0x0a] != 0x00) return false;
142   if (byHeader[0x0b] != 0x00) return false;
143   if (byHeader[0x0c] != 0xc0) return false;
144   if (byHeader[0x0d] != 0x00) return false;
145   if (byHeader[0x0e] != 0x00) return false;
146   if (byHeader[0x0f] != 0x00) return false;
147   if (byHeader[0x10] != 0x00) return false;
148   if (byHeader[0x11] != 0x00) return false;
149   if (byHeader[0x12] != 0x00) return false;
150   if (byHeader[0x13] != 0x46) return false;
151
152   // 2dwords, always 0
153   if (byHeader[0x44] != 0x0 ) return false;
154   if (byHeader[0x45] != 0x0 ) return false;
155   if (byHeader[0x46] != 0x0 ) return false;
156   if (byHeader[0x47] != 0x0 ) return false;
157   if (byHeader[0x48] != 0x0 ) return false;
158   if (byHeader[0x49] != 0x0 ) return false;
159   if (byHeader[0x4a] != 0x0 ) return false;
160   if (byHeader[0x4b] != 0x0 ) return false;
161
162   return true;
163 }