Undocument Windows API và VBA (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

ThangCuAnh

Mới rờ Ét xeo
Tham gia
1/12/17
Bài viết
896
Được thích
793
Giới tính
Nam
Nghề nghiệp
Coder nghỉ hưu, RCE dạo
Cái laptop hư lâu lắc, phải gởi vào thành hồ chứa mưa sữa, mới lấy về.
Nên quay lại tiếp với cái gọi là "rờ chxx em" Windows và VBA.
Topic này tui sẽ đăng lần lượt những gì cu anh tui phát hiện ra trong quá trình "rờ em" Windows API, DLLs và VBAxxx.dll. Các tips, tricks này sẽ bảo đảm không có trên ông "Gấu gồ". Và dùng được cho VBA trên Offices. Chứ "ưn đồ cú mèn" API mà chỉ dùng được cho C/C++, Delphi... thì dân tin học VP ở đây thua.
Tui chỉ sẽ tập trung ở các Windows DLL sau: kernel32.dll, shell32.dll, shlwapi.dll, oleaut32.dll, ole32.dll, advapi32.dll... và 1 ít từ ntdll.dll (core usermode API của Windows). Trên VBExxx.dll thì tui chỉ tập trung vào VBE6 của Office 2007, VBE7 của Office2010 32 và 64bit, các VBExxx.dll khác cũng sẽ gần như tương đượng, không khác nhau mấy.
 
Lần chỉnh sửa cuối:
Máy tui dỏm hơn máy bạn cả trăm lần mà chạy có vài phút à mà đơ cái gì :)
À quên, máy 1 nhân (1 CPU) phụ thuộc vào số thread set trong Excel settings nữa.
 
Upvote 0
OK bạn, đúng rồi bạn, dùng 4, bạn cứ test đi. Excel nó tự detect ra máy bao nhiêu nhân mà.
PS: À quên, các bạn sữa lại hàm DumpString như sau nhé, để nó dump full cả địa chỉ:
Mã:
'
' Dump memory content of a VBA string variable to hex bytes string
' Có the dùng cho Excel de xem các char di dang trong 1 chuoi trên cell
'
Public Function DumpString(ByRef strDump As String) As String
    If StrPtr(strDump) <> 0 Then
        ' Avoid BSTR pointer of strDump is NULL, when strDump was not initialized or was assigned = vbNullString
        DumpString = DumpMem(StrPtr(strDump) - 4, LenB(strDump) + 6)
    Else
        DumpString = DumpMem(VarPtr(strDump), PTR_SIZE)
    End If
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
chạy hàm DumpString củ đoán mất 1 giây chi đó có ngay tức thì
1.JPG
chạy hàm DumpString bài 103 thì nó lâu hơn
Capture.JPG
 
Lần chỉnh sửa cuối:
Upvote 0
Khổ ghê, chạy hàm DumpString ngoài Excel đó, đọc lại giúp cậu ơi
 
Upvote 0
Nó nằm bên topic lập trình Delphi bằng video đó bé
 
Upvote 0
2231401566389375956.png

Mã:
ABCDEF    41 00 42 00 43 00 44 00 45 00 46 00
    0C 00 00 00 41 00 42 00 43 00 44 00 45 00 46 00 00 00
    
    
    145F0758: 0C 00 00 00 41 00 42 00 43 00 44 00 45 00 46 00 00 00
 
Upvote 0
Kéo ABCDEF hết cột A, kéo B1 hết cột B.
Công thức B1= DumpString(A1).
DumpStrinh mới nhen.
Xong Remove Duplicate, xem còn lại mấy dòng ?
Cảm ơn bạn
 
Upvote 0
Kéo mỏi tay quá mai keo tiếp
223141
 
Upvote 0
Dùng hàm cũ rồi.
Ctrl c, ctrl shft down, ctrl v, ai biểu kéo = chuột chời
 
Upvote 0
@thuyyeu99 test giùm chú vụ này đi.
Nãy giờ máy chú Excel đang chạy đơ máy luôn, chú đang ép nó chạy 1 nhân. Máy bé mấy nhân ?
 
Upvote 0
Bé đọc, download file từ post 93 nhé.
 
Upvote 0
em không biết nó máy nhân nữa. của em win 7 32 bit
223166
 
Upvote 0
Máy em 4 nhân
Bài đã được tự động gộp:

Bạn mình hỏi vụ CreateThread, mình im lặng không trả lời vì muốn tìm cho ra Excel nó hoạt động thế nào, rõ mới trả lời. Đừng giận nhé bạn.
Đây là kết quả bắt Excel chạy 1 nhân, cho phép multithread. Nó sinh 1 worker thread ngoài thread chính để tính toán. Thread đó chạy song song trên 2 nhân.
Số vùng memory address cấp cho chuỗi ABCDEFGH trao đổi giữa VBA và Excel là 2.
Giờ trả về cho nó 2 nhân, chạy lại thử.
 

File đính kèm

  • 1.png
    1.png
    42.1 KB · Đọc: 15
  • 2.png
    2.png
    64.7 KB · Đọc: 15
  • 1.png
    1.png
    21.3 KB · Đọc: 13
Lần chỉnh sửa cuối:
Upvote 0
Máy em 4 nhân
Bài đã được tự động gộp:

Bạn mình hỏi vụ CreateThread, mình im lặng không trả lời vì muốn tìm cho ra Excel nó hoạt động thế nào, rõ mới trả lời. Đừng giận nhé bạn.
Đây là kết quả bắt Excel chạy 1 nhân, cho phép multithread. Nó sinh 1 worker thread ngoài thread chính để tính toán. Thread đó chạy song song trên 2 nhân.
Số vùng memory address cấp cho chuỗi ABCDEFGH trao đổi giữa VBA và Excel là 2.
Giờ trả về cho nó 2 nhân, chạy lại thử.
Cả triệu dòng không biết khi nào xong hichic
 
Upvote 0
Khi bật 2 nhân cho Excel, kết quả trên máy tôi, vùng nhớ trao đổi giữa VBA và Excel vẫn là 2, nhưng số thread tham gia tính toán thay đổi đáng kể.
Excel GUI thread (thread chính) giờ lên 2, Worker thread chính để tính toán vẫn là 1, nhưng tại sao lại có sự tham gia của các thread lạ của MSO.dll và 2 đến 3 từ ông Windows bắn ra ? Ông từ winmm.dll có thread priority cao nhất (Highest), ông từ ntdll.dll lâu lâu phọt ra 1 cái rồi biến mất, phải canh nhanh tay chụp màn hình mới được.
Sợ máy bà con nhanh quá không thấy rõ đâu.
 

File đính kèm

  • 3.png
    3.png
    22.6 KB · Đọc: 15
Upvote 0
Khi bật 2 nhân cho Excel, kết quả trên máy tôi, vùng nhớ trao đổi giữa VBA và Excel vẫn là 2, nhưng số thread tham gia tính toán thay đổi đáng kể.
Excel GUI thread (thread chính) giờ lên 2, Worker thread chính để tính toán vẫn là 1, nhưng tại sao lại có sự tham gia của các thread lạ của MSO.dll và 2 đến 3 từ ông Windows bắn ra ? Ông từ winmm.dll có thread priority cao nhất (Highest), ông từ ntdll.dll lâu lâu phọt ra 1 cái rồi biến mất, phải canh nhanh tay chụp màn hình mới được.
Sợ máy bà con nhanh quá không thấy rõ đâu.
Cái này ngoài tầm hiểu biết của em rồi :unknw: :unknw:
 
Upvote 0
Hì hì, tìm ra rồi. Excel Team chơi vầy ai chơi, đua cho lại nổi :) Chia buồm bạn mình :(
 
Upvote 0
Cảm ơn bé nhen, đúng mình suy đoán, 4 nhân 4 string.
Hì hì, test tính năng có phải code của Excel đã được code, build và dùng tính năng chạy đa luồng, đa nhân đó em.
Tội nghiệp ông VBA, đứng giữa Excel với VBA coder, phải è cổ phục vụ khi VBA coder yêu cầu, rồi phải đứng giữa VBA coder với API nữa, cũng phải è cổ mà chạy phục vụ. Nhưng cũng được cái ưu ái là chạy trong 1 thread riêng. Hì hì, không phải tốt vậy đâu, tại thằng Excel nó sợ mày chết ảnh hưởng tao, nên đá mày ra đường đất riêng, đường rộng tao đi cho an toàn. Code của VBEx.dll chỉ được build đơn luồng, đơn nhân mới ác chứ.
Trong đây chỉ thằng oleaut32.dll với cái cache là sướng nhất. OANOCACHE = OLE Allocating No Cache. Bật cờ này lên thằng oleaut32.dll này mới vắt chân lên cổ mà chạy, không thì nó chơi trò ăn gian, làm biếng cấp mới, cứ cache các vùng nhớ yêu cầu cấp bởi SysAllocXXX API hết.
Nghĩ mà tội nghiệp cho Delphi GetMem, làm đủ cách, bao nhiêu năm, cuối cùng cũng phải thua trò Undocument của MS này.
 

File đính kèm

  • 1.png
    1.png
    46.2 KB · Đọc: 15
  • 3.png
    3.png
    47.5 KB · Đọc: 19
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn bé nhen, đúng mình suy đoán, 4 nhân 4 string.
Hì hì, test tính năng có phải code của Excel đã được code, build và dùng tính năng chạy đa luồng, đa nhân đó em.
8 nhân 8 string
Why ?

Anh có thể giải thích dễ hiểu chúc hơn được không em xắp thắm thắm rồi
 
Lần chỉnh sửa cuối:
Upvote 0
Bé hỏi tụi Excel team đó, cho em xem code Excel của tụi anh đi ? :)
Test sáng giờ, từ hôm qua tới giờ, vì đã nghi nghi rồi. Có nói với bạn mình, thua họ, các hàm built-in của họ thôi, làm sao mà thắng nổi họ, ngang ngang 8-90% của họ là mừng rồi. Cái đó là cái ngưỡng người bình thường không thể vượt qua, phải chấp nhận thôi.
Hì hì, nhưng phát hiện ra cái này, Excel Team chơi chưa khủng đâu, chưa bằng Chrome. Trong lúc chạy, chờ đợi kết quả, mới phát hiện ra là ông Excel không đụng chạm gì đến GPU cả, còn ông Chrome mà nặng tải là ổng nhảy qua dùng GPU tính dùm luôn. Vừa đa process,đa luồng,đa nhân, giờ chơi luôn với GPU. Cửa thắng Excel là ở đây thôi.
Đúng là thiên hạ "nắm nắm" người tài.
 
Upvote 0
Bé hỏi tụi Excel team đó, cho em xem code Excel của tụi anh đi ? :)
Test sáng giờ, từ hôm qua tới giờ, vì đã nghi nghi rồi. Có nói với bạn mình, thua họ, các hàm built-in của họ thôi, làm sao mà thắng nổi họ, ngang ngang 8-90% của họ là mừng rồi. Cái đó là cái ngưỡng người bình thường không thể vượt qua, phải chấp nhận thôi.
Hì hì, nhưng phát hiện ra cái này, Excel Team chơi chưa khủng đâu, chưa bằng Chrome. Trong lúc chạy, chờ đợi kết quả, mới phát hiện ra là ông Excel không đụng chạm gì đến GPU cả, còn ông Chrome mà nặng tải là ổng nhảy qua dùng GPU tính dùm luôn. Vừa đa process,đa luồng,đa nhân, giờ chơi luôn với GPU. Cửa thắng Excel là ở đây thôi.
Đúng là thiên hạ "nắm nắm" người tài.
Ua cái thằng Chrome no liên quan tới đồ họa nhiều hơn excel chứ anh nên có thể Excel team không muốn dùng chăng..

Thôi em đi lại xe đạp đây, đi máy bay chóng mặt quá:;;;::::;;;::::;;;::::;;;::::;;;::::;;;:::
 
Upvote 0
Chỉ người trong team họ mới biết chính xác họ làm gì thôi bé. Mình test vầy chỉ là đưa ra kết luận kiểu suy đoán, vì anh chưa "rờ em" thằng Excel với mso.dll, do nó bự quá mà không có pdb symbol nữa.
Bài đã được tự động gộp:

Thế bé đã hiểu hàm DumpMem, DumpString nó làm gì, nhiệm vụ gì chưa vậy ? :)
Bài đã được tự động gộp:

Giờ bé tự test trên máy bé đi, máy bé nhanh mà, tắt multithread, test 1 nhân, 2 nhân, 3 nhân, 4 nhân, rồi bật multithread, test 1 nhân, 2 nhân, 3 nhân, 4 nhân. Phần setting số nhân đó chú úp cái hình rồi.
Bài đã được tự động gộp:

Nói chung là giờ bạn mình chỉ test cái XLL Delphi của bạn mình được chạy trong thread nào của Excel. Chạy trong thread chính GUI thread thì thua, nếu chạy trong Worker thread của nó cũng thua, nhưng thua ít ít, vì các hàm của nó chạy đa nhân.
Nói chung là thua hết, nên phải tìm hiểu kỹ, sâu về multithread trong Delphi, xuống dưới API thật kỹ luôn. Xem Delphi có support parallel,đa nhân không rồi dùng cho tối ưu nhất. Nếu Delphi support GPU thì dùng GPU đua luôn.
Đó là trước mắt muốn ngang nó hoặc may mắn thì hơn nó chút xíu.
Chứ đầu tụi nó toàn thiên tài, có sạn hết. Người bình thường không có cửa qua. Chưa kể mấy cái giấu, undocument của tụi nó nữa. SDK mà còn giấu, xóa bớt đi mà :)
 
Lần chỉnh sửa cuối:
Upvote 0
Theo lý thuyết thì chúng ta tin rằng chuỗi Ax là 1 thì chuỗi xuống tới VBA chỉ là 1 thôi đó bé. Nôm na cho dễ hiểu và tin vậy đi, biết nhiều khổ, nhức đầu chứ được gì đâu :)
Tự nhiên cảm thấy buồn, nản nản. Biết thêm về 1 điều mà mình không thể vượt qua thì nó buồn hơn vui.
GCC với OpenMP: Open Multi Processor Library có thể vượt qua Excel. Chứ dùng Delphi hay VC++ thuần mà tính dùng multithread để chạy đua với Excel Team thì cũng tốn công vô ích ! Code multithread lại họ không đã ? Tại sao họ chỉ sinh đúng 1 worker thread chạy hết công suất để tính toán ?Trong khi ở đây họ dùng cả parallel, multi processor nữa !
Còn ai ngoài MS nắm rành nhất về hệ điều hành của họ, ngôn ngữ C/C++ của họ, IDE của họ, compiler của họ, thư viện C/C++ của họ, SDK của họ, API của họ, các Undocument của họ, sản phẩm cũng của chính họ !!!!!!!!?????????????
 
Lần chỉnh sửa cuối:
Upvote 0
Chưa kể bao nhiêu nhân tài IT về đầu quân cho MS: cha đẻ Delphi, cao thủ số 1 về C++ thế giới (ngang ngữa cha đẻ C++) cũng về MS phụ trách team viết Universal C++ Library: thư viện C++ chạy đa hệ điều hành, IOT. Các cao thủ số 1, số 2 thế giới về security cũng về MS, như Skype, về MS, phát minh ra Delay Loading, thay thế static link và dynamic call MS phải dùng bao nhiêu năm. Code hàm _delayLoadHelper trong C RTL của VC++ cũng do chính tay ông ta viết.
VN mình tui biết, quen vài người số 1 về security đã và đang làm cho MS: Bruce Dang, Thug4Life... Google thì có Dương Ngọc Thái (morro), người viết cái bài Học An Toàn Thông Tin thì phải học gì mà tôi vừa post bên kia cho bé @thuyyeu99 đọc đó.
Và người ta còn đồn đoán, và đã có xác nhận là MS có những tool, compiler, thư viện hoàn toàn dùng internal riêng trong cty, không bao giờ release ra ngoài. Dùng riêng cho sp của họ.
Chuyện vui chút: hồi Windows 2000 source code bị leak, gần như chứa 80-90% cả Windows ở tầng Kernel và User,người ta ùa nhau download, MS bó tay không chặn được. Sau đó nhiều người xem phải khen các kỹ sư của MS quá siêu, quá giỏi, họ code C/C++ gần như vô địch.
Và trong đó nhiều chuyện cười, MS coder cũng goto, workaround, tà đạo tá lã âm binh, và trong comment nhiều cái buồn cười. Họ cũng fuck fiec chữi nhau, chửi team khác,đổ thừa qua lại, workaround tạm cho các sp của cty khác ở ngoài chạy được.
Lúc đó tui cũng download được, ghi đúng 1 đĩa CD. Giờ nó đâu mất tiêu rồi :)
 
Lần chỉnh sửa cuối:
Upvote 0
MỚI COI TẸO Việt nam mình nhân tài khá nhiều đấy
Lâu lâu hay ngó tẹo
 
Upvote 0
Uhm, các bạn trẻ này bên Viettel Security
 
Upvote 0
Hì hì, thế giờ tin cái vụ TDS symbols chưa ?
 
Upvote 0
HÌnh như trong Delphi nó cho tắt đi đấy

.....................
Tôi chỉ có một phần
trong phần mềm của chúng tôi.
(Bản án dự án yêu cầu Phần mềm C ++ Builder)

Các phần mềm của phần mềm Delphi (32 và 64 bit!):
- Biên dịch vụ của bạn và bạn "TD32" (D7?)
- Tách thông tin TD32 thành thành
tdstrp32.exe -s <yourproject.exe>
Lưu ý: không có phần mềm của bạn -s với exe 64 bit -> nó làm cho bạn exe của bạn! (.tds là OK)
- Tối ưu hóa .tds thành công .pdb.
tds2pdb.exe <yourproject.tds>
- của bạn
- Phần cứng và phần mềm, phần mềm và phần mềm.
- WinDbg.exe (Công thức tính toán của Microsoft cho Windows, x86 cho 32 bit, x64 cho 64 bit)
- Phần mềm -> bản hướng dẫn
- Phá phá
- Phần mềm ->
- Hacker
- Hacker -> hoàng ván ->
- Xem phần mềm của bạn và bạn -> bạn có thể "
 
Upvote 0
Cái vụ layout của bảng VMT của 1 object trong Delphi, nó nằm trong bộ nhớ ra sao, tui cũng đã post rồi, tại bạn không chịu đọc thôi. Đọc cái link bạn vừa post thì cần phải xem lại cái link hồi trước tui post bên kia, link về Internal Data của Delphi đó. Mới hiểu tại sao được.
Hì hì,à mà bạn tắt TDS đi thì cũng vô ích thôi. Vì nó hổ trợ cho coder debug code của họ. Chứ build release thì vẫn có cách lấy lại code Delphi của bạn, chỉ mất thời gian hơn thôi. Vd có TDS thì 1, không có TDS thì 3-5 thôi. Kiên nhẫn là ra hết :)
 
Upvote 0
coi tới lui ròi tại trình kém chưa hiểu tới
ngay code tại GPE này có file Mạnh Lưu lại mấy năm sau coi lại mới à lên 1 cái thì ra nó thế

Thấy mấy trang nó keo trong Delphi nên tắt RTTI đi thì dung lượng file giản + abcxzy
 
Lần chỉnh sửa cuối:
Upvote 0

File đính kèm

  • 1.png
    1.png
    19.3 KB · Đọc: 22
Lần chỉnh sửa cuối:
Upvote 0
Tại trang đó 1 thời là số 1 thế giới về hack, RE, toàn thứ dữ trong đó
 
Upvote 0
code đó trên Delphi Mạnh mò hoài ko ra !!!??? thuộc hàng bí mật
 
Upvote 0
Chỉ người trong team họ mới biết chính xác họ làm gì thôi bé. Mình test vầy chỉ là đưa ra kết luận kiểu suy đoán, vì anh chưa "rờ em" thằng Excel với mso.dll, do nó bự quá mà không có pdb symbol nữa.
Bài đã được tự động gộp:

Thế bé đã hiểu hàm DumpMem, DumpString nó làm gì, nhiệm vụ gì chưa vậy ? :)
Bài đã được tự động gộp:

Giờ bé tự test trên máy bé đi, máy bé nhanh mà, tắt multithread, test 1 nhân, 2 nhân, 3 nhân, 4 nhân, rồi bật multithread, test 1 nhân, 2 nhân, 3 nhân, 4 nhân. Phần setting số nhân đó chú úp cái hình rồi.
Bài đã được tự động gộp:

Nói chung là giờ bạn mình chỉ test cái XLL Delphi của bạn mình được chạy trong thread nào của Excel. Chạy trong thread chính GUI thread thì thua, nếu chạy trong Worker thread của nó cũng thua, nhưng thua ít ít, vì các hàm của nó chạy đa nhân.
Nói chung là thua hết, nên phải tìm hiểu kỹ, sâu về multithread trong Delphi, xuống dưới API thật kỹ luôn. Xem Delphi có support parallel,đa nhân không rồi dùng cho tối ưu nhất. Nếu Delphi support GPU thì dùng GPU đua luôn.
Đó là trước mắt muốn ngang nó hoặc may mắn thì hơn nó chút xíu.
Chứ đầu tụi nó toàn thiên tài, có sạn hết. Người bình thường không có cửa qua. Chưa kể mấy cái giấu, undocument của tụi nó nữa. SDK mà còn giấu, xóa bớt đi mà :)

Mấy ngày nay em bận chạy ngoài đường không test mấy cái Jump bô của bác được. Tối vẫn mải miết làm “công trình”, nhưng vấn đề muiltithread trong Excel lại một lần nữa em đang dự là khó ngủ ngon :( .
 
Upvote 0
Già, thấy mệt rồi, kg còn muốn đua thắng thua nữa, mà thấy 99%là thua trắng rồi
 
Lần chỉnh sửa cuối:
Upvote 0
Em ngồi đọc lại máy bài trong mục này giờ mới nghiệm ra được một ít (*%(*%(*%(*%(*%
 
Upvote 0
Nghiệm được gì bé, share chú với
 
Upvote 0
Bé cứ mạnh dạn nói đi
 
Upvote 0
Tối qua say quá, lênGPE nói bậy bạ, sorry bà con nhen. Nay nghỉ làm, lên GPE bà 8 chút cho vui.
Hôm nay và về sau ta sẽ xem:
1. MsgBox của VBA có tricks gì giấu không, làm sao hiển thị được chuỗi Unicode? (Không phải MessageBoxA/W API nhé các bạn)
2. Các hàm ObjPtr, StrPtr, VarPtr thực chất là gì ? Bản chất 1 object của VBA trong bộ nhớ nó "như thế lào". Variant thì ta đã có hàm DumpVariant dùng DumpMem để xem trong ruột Variant là gì rồi.
3. Code VBA của ta sau khi được biên dịch ra mã máy sẽ chạy trong thread nào, thread của VBEx.dll (đã được Excel cha sinh ra cho) hay được VBA sinh ra thread mới cho ta chạy riêng, và khi ta debug code từng bước, code ta chạy trong thread nào ?
4. Implement hàm TypeName sau khi đã "rờ em" nó = chính VBA và API. Hì hì, chứ thuần VBA không thì thua.
5. Làm sao gọi con trỏ hàm stdcall API trong VBA. Với hàm khác stdcall như _cdecl thì thua, bó tay, phải dùng cách 6. Chứ với stdcall trên Win32 thì được, ta sẽ gọi từ VBA ra sao, chỉ cần gọi được các hàm có 1, 2 và 3 tham số.
Vd trên VBA ta đã GetProcAddress được 1 hàm, làm sao call nó luôn.
Cách này tựa tựa như cơ chế, struct VBDllFunctionCall của VB/VBA.
Trên Win64 thì không còn khái niệm stdcall, fastcall, cdecl... call ciếc gì linh tinh nữa. Tất cả về chỉ 1 kiểu gọi duy nhất, register call. Thanks MS, Intel và AMD :)
6. Cách gọi 1 array of byte của VBA chứa mã ASM trực tiếp ra sao ? Vd: push ebp, mov ebp, esp huyền thoại = 55 8B EC, mov edi, edi tại đầu hàm bất kỳ hàm API nào của MS = 8B FF. Mấy thằng hacker, virus quờ rai tơ, ex pờ loi ter hay chơi trò tà đạo này.
7. Dài hơi hơn, rờ ngược lên trên Excel.exe và mso.dll, xem có gì hay không :p
8... Còn gì nữa ta, bà con góp ý nhé.

Nói chung là hay dùng nhiều, vd MsgBox (rtcMsgBox), mà quên để ý nó như thế lào ?
Bài đã được tự động gộp:

Cứ ghim cái này ở đây cho dễ tra, bà con dùng DumpVariant thấy 2 byte đầu tiên là chính là cái enum này:
Mã:
FFFFFFFF ; enum VARENUM, copyof_712
FFFFFFFF VT_EMPTY  = 0
FFFFFFFF VT_NULL  = 1
FFFFFFFF VT_I2    = 2
FFFFFFFF VT_I4    = 3
FFFFFFFF VT_R4    = 4
FFFFFFFF VT_R8    = 5
FFFFFFFF VT_CY    = 6
FFFFFFFF VT_DATE  = 7
FFFFFFFF VT_BSTR  = 8
FFFFFFFF VT_DISPATCH  = 9
FFFFFFFF VT_ERROR  = 0Ah
FFFFFFFF VT_BOOL  = 0Bh
FFFFFFFF VT_VARIANT  = 0Ch
FFFFFFFF VT_UNKNOWN  = 0Dh
FFFFFFFF VT_DECIMAL  = 0Eh
FFFFFFFF VT_I1    = 10h
FFFFFFFF VT_UI1   = 11h
FFFFFFFF VT_UI2   = 12h
FFFFFFFF VT_UI4   = 13h
FFFFFFFF VT_I8    = 14h
FFFFFFFF VT_UI8   = 15h
FFFFFFFF VT_INT   = 16h
FFFFFFFF VT_UINT  = 17h
FFFFFFFF VT_VOID  = 18h
FFFFFFFF VT_HRESULT  = 19h
FFFFFFFF VT_PTR   = 1Ah
FFFFFFFF VT_SAFEARRAY  = 1Bh
FFFFFFFF VT_CARRAY  = 1Ch
FFFFFFFF VT_USERDEFINED  = 1Dh
FFFFFFFF VT_LPSTR  = 1Eh
FFFFFFFF VT_LPWSTR  = 1Fh
FFFFFFFF VT_RECORD  = 24h
FFFFFFFF VT_INT_PTR  = 25h
FFFFFFFF VT_UINT_PTR  = 26h
FFFFFFFF VT_FILETIME  = 40h
FFFFFFFF VT_BLOB  = 41h
FFFFFFFF VT_STREAM  = 42h
FFFFFFFF VT_STORAGE  = 43h
FFFFFFFF VT_STREAMED_OBJECT  = 44h
FFFFFFFF VT_STORED_OBJECT  = 45h
FFFFFFFF VT_BLOB_OBJECT  = 46h
FFFFFFFF VT_CF    = 47h
FFFFFFFF VT_CLSID  = 48h
FFFFFFFF VT_VERSIONED_STREAM  = 49h
FFFFFFFF VT_BSTR_BLOB  = 0FFFh
FFFFFFFF VT_ILLEGALMASKED  = 0FFFh
FFFFFFFF VT_TYPEMASK  = 0FFFh
FFFFFFFF VT_VECTOR  = 1000h
FFFFFFFF VT_ARRAY  = 2000h
FFFFFFFF VT_BYREF  = 4000h
FFFFFFFF VT_RESERVED  = 8000h
FFFFFFFF VT_ILLEGAL  = 0FFFFh
 
Lần chỉnh sửa cuối:
Upvote 0
Đụng cái bốp vào đá rồi, ITypeInfo GetDocumentation method đòi 5 tham số lận, hu hu hu :(
Để "rờ" lại thằng rtcTypeName của VBA có đúng nó dùng ITypeInfo không !
 

File đính kèm

  • 1.png
    1.png
    9.8 KB · Đọc: 16
Lần chỉnh sửa cuối:
Upvote 0
Hì hì, sorry bà con, lanh chanh đoản, chuỗi của ta xuống tới rtcMsgBox vẫn còn "Jin", nguyên bản, nhưng vào sâu bên trong thì bị convert mất. Khúc đầu không phải lỗi của VBA :)
MsgBox -> xyx -> rtcMsgBox -> xyz -> W2MBCS -> MessageBoxIndirectA.
Vậy nên kết thúc MsgBox, rtcMsgBox ở đây, không có cách nào dùng nó hiển thị chuỗi Unicode có dấu được. Bà con phải dùng cái khác như call trực tiếp API MessageBoxW(StrPtr(xxx),...) hay mấy cái shell siếc gì đó linh tinh.
Có cái message box thôi mà rtcMsgBox làm gì mà khủng khiếp quá.
 

File đính kèm

  • 1.png
    1.png
    20.1 KB · Đọc: 19
Lần chỉnh sửa cuối:
Upvote 0
Độc thoại một mình chán quá. Nói chuyện 1 mình y như thằng khùng :(
 
Upvote 0
mấy cái lọ mọ tò mò này Mạnh cũng ham lắm mà coi tới lui ko biết chi luôn ... nên ko biết chi mà tám cho vui vẻ cả
 
Upvote 0
@ThangCuAnh anh có thể check giùm em cái is nothing được không. Em làm đủ kiểu trong delphi mà không được.
 
Upvote 0
Diễn đàn GPE em thấy được mấy anh cũng rành Memory, buff,,,,,,,, mà cũng lạ là chưa thấy mấy ảnh Comment nhỉ ===\. ===\. ===\. ===\. ===\. ===\.

Lĩnh vực IT có nhiều lắm, mỗi người chuyên riêng. Nhưng món debug memory rồi “rờ e” như bác TQN đang làm trên là của hiếm đấy bạn bạn nha.
 
Upvote 0
Lĩnh vực IT có nhiều lắm, mỗi người chuyên riêng. Nhưng món debug memory rồi “rờ e” như bác TQN đang làm trên là của hiếm đấy bạn bạn nha.
Em chưa hiểu rờ e Là gì
TQN ?
Mà em thấy ảnh debug memory, rồi dịch code dll là em thấy quá siêu rồi
 
Upvote 0
Kg chịu xem kỹ cái hình bên kia, khi nào thì nó trả về "Nothing", khi nào là "Object", khi nào là name thật
 
Lần chỉnh sửa cuối:
Upvote 0
Hì hì, nghe hỏi mình mới sực nhớ. Trước giờ cứ nghĩ VBA có hàm IsNothing, giờ xem lại hổng có có :) rtcIsNothing cũng hổng có luôn. Chỉ có statement Is Nothing. Thế nó là cái gì. Lò mò xem vào phần parse code VBA của người dùng, mình mới ngã ngữa, những cái select case (switch case...) khổng lồ, cái nào cũng 6, 7 ngàn case :p
X Is Nothing được parse và nhảy tới hàm _lblEx_LitNothing, nằm trong 1 bảng có tên là tblByteDisp, 400 phần tử.
"Rờ em" VBEx.dll học được rất nhiều điều hay từ MS coder, nhưng cũng kèm theo đó là thất vọng về sự vất vã, nặng nề, chậm chạp của VBA :(
 
Upvote 0
trên GPE này nhiều năm thấy dân chúng lập nhiều thớt tám qua lại các kiểu cái vụ Set Dít = nothing .... vậy mò trong đó nó nói sao he @ThangCuAnh
 
Upvote 0
"Set x = Nothing" khác "Is Nothing"
Không cần mò đâu, cậu Mạnh dùng DumpMem với 1 biến object sẽ thấy ObjPtr là gì, nothing là gì, chưa có gì khi mới khai báo là gì. Thử đi, có sẵn đồ nghề rồi đó
 
Upvote 0
DumpMem với Object ra được gì chưa bạn Mạnh ?
 
Upvote 0
Tiếng anh dịch không sát nghĩa mệt thệt hihihihi
 
Upvote 0
Các bạn chạy thử đoạn code này với file ở post #93 nhé:
Mã:
Option Explicit

Public Sub Test_Object()
    Dim obj As Object
    Dim v As Variant

    Debug.Print "------- obj chua duoc khoi tao -------------"
    DumpMem VarPtr(obj), PTR_SIZE
    Debug.Print "------- v chua duoc khoi tao ---------------"
    DumpVariant v
    
    Debug.Print "------- obj duoc set = nothing -------------"
    Set obj = Nothing
    DumpMem VarPtr(obj), PTR_SIZE
    
    Debug.Print "------- v duoc set = obj--------------------"
    Set v = obj
    DumpVariant v               ' <= @thuyyeu99 chú ý o day
    Debug.Print v Is Nothing
    
    Debug.Print "------- obj duoc khoi tao tu 1 class -------"
    Set obj = CreateObject("Scripting.Dictionary")  ' ref count = 1
    DumpMem VarPtr(obj), PTR_SIZE
    Debug.Print "Pointer to the object instance of obj = " & Hex$(ObjPtr(obj))
    DumpMem ObjPtr(obj), PTR_SIZE
    
    obj.Add 0, 1
    obj.Add 1, 2
    Debug.Print "Dictionary object có Count = " & obj.count

    Debug.Print "------- v duoc set = obj -------------------"
    Set v = obj     ' ref count = 2
    DumpVariant v
    
    Debug.Print "------- obj duoc set = nothing tro lai -----"
    Set obj = Nothing   ' ref count xuong còn 1
    DumpMem VarPtr(obj), PTR_SIZE

    Debug.Print "------- v van giu pointer to obj dict ------"
    DumpVariant v
    
    v.Add 2, 3
    v.Add 3, 4
    
    Debug.Print "Dictionary object có Count = " & v.count
    DumpVariant v
    
    Debug.Print "------- v = Empty, Erase obj dict ----------"
    v = Empty           ' ref count = 0, object dictionary duoc giai phóng (free)
    DumpVariant v
    
    ' v.Add 4, 5    ' <= die here
End Sub
 
Upvote 0
Em dịch rồi anh giải quyết được vấn Is Nothing rồi ah, do em hiểu sai nghĩa thôi. Còn hàm check range viết trong Addin giờ em rút gọn chỉ cần 1 dòng Code thôi hihii
 
Upvote 0
mới thử xong ... nó như sau:
Mã:
------- obj chua duoc khoi tao -------------
003FEBD0: 00 00 00 00
------- v chua duoc khoi tao ---------------
003FEBC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
VarType:
00 00
Reserved1-3:
00 00 00 00 00 00
Data:
00 00 00 00 00 00 00 00
------- obj duoc set = nothing -------------
003FEBD0: 00 00 00 00
------- v duoc set = obj--------------------
003FEBC0: 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
00 00 00 00 00 00 00 00
True
------- obj duoc khoi tao tu 1 class -------
003FEBD0: 58 65 F9 06
Pointer to the object instance of obj = 6F96558
06F96558: 1C 15 28 6B
Dictionary object có Count = 2
------- v duoc set = obj -------------------
003FEBC0: 09 00 00 00 00 00 00 00 58 65 F9 06 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 65 F9 06 00 00 00 00
------- obj duoc set = nothing tro lai -----
003FEBD0: 00 00 00 00
------- v van giu pointer to obj dict ------
003FEBC0: 09 00 00 00 00 00 00 00 58 65 F9 06 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 65 F9 06 00 00 00 00
Dictionary object có Count = 4
003FEBC0: 09 00 00 00 00 00 00 00 58 65 F9 06 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 65 F9 06 00 00 00 00
------- v = Empty, Erase obj dict ----------
003FEBC0: 00 00 00 00 00 00 00 00 20 5C 20 0C 00 00 00 00
VarType:
00 00
Reserved1-3:
00 00 00 00 00 00
Data:
20 5C 20 0C 00 00 00 00
 
Upvote 0
Và kết quả chạy code sẽ ra như sau, trên máy các bạn nó khác ở chỗ xxxxxxxx: thôi nhé.
Mã:
------- obj chua duoc khoi tao -------------
1. 0030ED68: 00 00 00 00
------- v chua duoc khoi tao ---------------
2. 0030ED58: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
VarType:
3. 00 00
Reserved1-3:
00 00 00 00 00 00
Data:
4. 00 00 00 00 00 00 00 00
------- obj duoc set = nothing -------------
5. 0030ED68: 00 00 00 00
------- v duoc set = obj--------------------
6. 0030ED58: 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
VarType:
7. 09 00
Reserved1-3:
00 00 00 00 00 00
Data:
00 00 00 00 00 00 00 00
True
------- obj duoc khoi tao tu 1 class -------
8. 0030ED68: 98 17 64 00
9. Pointer to the object instance of obj = 641798
10. 00641798: 88 4B 31 72
Dictionary object có Count = 2
------- v duoc set = obj -------------------
11. 0030ED58: 09 00 00 00 00 00 00 00 98 17 64 00 00 00 00 00
VarType:
12. 09 00
Reserved1-3:
00 00 00 00 00 00
Data:
13. 98 17 64 00 00 00 00 00
------- obj duoc set = nothing tro lai -----
14. 0030ED68: 00 00 00 00
------- v van giu pointer to obj dict ------
15. 0030ED58: 09 00 00 00 00 00 00 00 98 17 64 00 00 00 00 00
VarType:
16. 09 00
Reserved1-3:
00 00 00 00 00 00
Data:
17. 98 17 64 00 00 00 00 00
Dictionary object có Count = 4
18. 0030ED58: 09 00 00 00 00 00 00 00 98 17 64 00 00 00 00 00
VarType:
19. 09 00
Reserved1-3:
00 00 00 00 00 00
Data:
20. 98 17 64 00 00 00 00 00
------- v = Empty, Erase obj dict ----------
21. 0030ED58: 00 00 00 00 00 00 00 00 10 64 E4 04 00 00 00 00
VarType:
22. 00 00
Reserved1-3:
00 00 00 00 00 00
Data:
23. 00 00 00 00 00 00 00 00
 
Upvote 0
Tôi sữa lại bên kết quả tôi chút để các bạn dễ đọc và thắc mắc tại dòng 1 -> 23, là những chỗ quan trong, các bạn cứ mạnh dạn bắt bẻ, vặn vẹo nhé.
Chổ quan trong nhất là chỗ 10, cần dài dòng và hình ảnh hơn để giải thích, giờ tập trung phần thô trước đã.
 
Upvote 0
if assigned(object)=false then isNothing
Range thì anh tìm hiểu Supports hoặc IDispatch , QueryInterface giống như anh "TCA" nói ở máy bài đầu ý
Thường thì Mạnh làm vầy

Mã:
object:= CreateOleObject('Scripting.Dictionary')
....
object:= Unassigned;
 
Upvote 0
@thuyyeu99 chạy thử code chưa, có chú ý gì ở chổ anh note không ?
 
Upvote 0
Số 9 là VarType gì bé?
 
Upvote 0
vâng trong Delphi varDispatch nó là số 9 thì sao anh, em chua hiểu ý anh lắm ? (Tự về máy cái Memory em chưa hiểu lắm, mới sơ sơ chưa được tới lớp chồi nữa anh)
Từ cái số 9 em mới check is no thing và is range223261
 
Lần chỉnh sửa cuối:
Upvote 0
Hình bên kia với kết quả dump nó ra rõ ràng vậy mà Thủy chưa hiểu hả trời
 
Upvote 0
Tiếp tục Todo list, do bà con không có góp ý gì cả, nên tui đưa thêm cái của tui vào.
8. Bản chất thật sự của ByVal ByRef là gì, ByVal biến kiểu String nó hành VBA khổ ra sao, sự nguy hiểm khi truyền ByVal cho biến kiểu Variant và Object ? Bản chất của hàm return về String, Variant, Object là gì, nguy hiểm gì, nặng nề, vất vã cho VBA ra sao.
Hiểu được rồi chúng ta sẽ hiểu tại sao các hàm trong VBEx.dll, MS coder luôn truyền = Pointer: pointer to VARIANT, BSTR pointer, tại sao thằng VARIANT *pResult luôn luôn được truyền đầu tiên và trả về chính nó.

Nói chứ càng phân tích thấy càng tội VBA, thà cứ như C/C++ 1-1 thì MS coder khỏe biết mấy rồi, nó chạy siêu nhanh rồi. Do phải vừa đảo bảm sự tương thích với Windows củ, Office cũ, bảo đãm tính dễ học, dễ viết, dễ dùng cho người dùng, nên nó phải âm thầm vất vả cáng đáng quá nhiều thứ, rồi bị đổ thêm tội "lanh chanh" nữa.
Đeophai nó cũng có lanh chanh, nhưng nó sát với C/C++ nên cái tội lanh chanh của nó còn chấp nhận được, bỏ qua khi coder hiểu.
Đúng là cái gì cũng có cái giá của nó, ông trời không bao giờ cho không ai cái gì :(
 
Lần chỉnh sửa cuối:
Upvote 0
Class Dictionary của VBA: Scripting.Dictionary trong scrrun.dll được dùng nhiều nhất với dân dùng VBA. Chúng ta sẽ mổ xẻ nó, từ VBA ta sẽ lấy cho được 1 con số quan trọng nhất của nó: Reference Count. Con số này quyết định sự sống chết của Dictionary Object và mọi COM Object trên Windows và Offices khác mà dân VBA thấy, vd từ Excel ta thấy mọi thứ như ActiveCell, ActiveSheet, Range.... Tất tần tật.
Class Dictonary được Implement trong Scrrun.dll với tên class là VBADictionary. Nó implement các interface sau theo thứ tự từ cha đến con:
1. IUnknown với QueryInterface, AddRef, Release methods.
2. IDispatch với GetTypeInfoCount, GetTypeInfo, GetIDsOfNames và Invoke
3. IProvideClassInfo: vài method các bạn không thấy trong hình do nằm dưới.
4. IExternalConnection: nt
5. VBAEnumSupport: Internal declare của VBA, phục vụ cho vụ For Each, Next....
Bảng VMT table của VBADictionary còn thiếu vài field đầu, do nó được assign trước contructor
Mã:
this[0] = vtable of VBADictionary
this[1] = vtable of IUnknown
this[2] = vtable of IDispatch
Tiếp theo là 3 và xxx thì các bạn thấy trong hình.
Xem cho biết thôi, chúng ta chỉ cần xem cái this[5], cái Reference Counter, nó chính là VALUE AT ADDRESS = ObjPtr(dic) + 5 * PTR_SIZE. PTR_SIZE = 4 TRÊN OFFICE 32, 8 TRÊN OFFICE 64.


Untitled.png
 
Lần chỉnh sửa cuối:
Upvote 0
Hiện Mạnh đang xài 2 kiểu Dic trong Delphi ( Từ ngữ hay thuật ngữ code có thẻ Mạnh viết sai bét nhè ... nên ko cố chấp sai thì sửa thế thôi ?! )
Kiểu 1 theo cách hay viết trên VBA
Mã:
Dic := CreateOleObject('Scripting.Dictionary');
Kiểu 2 theo cách Mạnh Học trên Google
Mã:
Dic := TDictionary<string, Integer>.create;
Vậy có cách nào khác khi viết trên Delphi ta kết nối trực tiếp vào Dic đó trong thư viện C/c++ của Bill ko Or có cách nào đó hay hơn 2 cách trên khi @ThangCuAnh mở sẻ thư viện của Bill vvv...
 
Upvote 0
Các bạn nào đã lập trình COM/OLE sẽ hiểu được tầm quan trong của 2 method AddRef và Release của IUnknown: interface cha, cố nội của mọi inteface. Luôn luôn theo quy ước: AddRef: tăng reference counter lên 1, Release giảm reference counter xuống 1, nếu nó xuống tới 0: tự nó giải phóng nó.
Trên VBA, AddRef sẽ được gọi khi nào, khi chúng ta create nó = New hay CreateObject, khi chúng ta assign vào biến khác, khi chúng ta truyền nó đi bằng ByVal, khi chúng ta trả nó về từ kết quả hàm.
Release được gọi khi nào, dạ, cu anh em xin trả lời ạ, nó được VBA gọi khi Set nó = Nothing, khi nó ra khỏi scope: tầm vực, ví dụ tầm vực của hàm, khi object cha nó chết...
Vậy làm sao cho không bị leak, tức nó cứ sống hoài, thì cứ phải theo nguyên tắc 1 - 1, có AddRef thì phải có Release, tức có tăng 1 thì phải có giảm 1. Để khi xuống tới 0 nó tự delete nó.1.png2.png
Bài đã được tự động gộp:

TDictionary là class của Delphi, viết = Object Pascal, có source nó đâu đó đó trong thư mục source của Delphi đó. Nó không dính dáng, liên quan gì đến Dictionary của VBA cả.
Muốn thì dùng cái nào cũng được, nhưng cái Dic của VBA chắc chắn sẽ chạy nhanh hơn TDict của Delphi.
 
Upvote 0
vậy là có Set Dic = ... thì bắt buột phải có Set Dic = nothing ???
nếu ko set Dic = nothing thì điều gỉ sẻ xẩy ra ???

Vậy nếu sử dụng Dic của VBA nhanh hơn ... thì trong Delphi ngoài cách sau thì có cách khai báo nào khác hay hơn
Mã:
Dic := CreateOleObject('Scripting.Dictionary');
 
Upvote 0
Thì Reference counter nó vẫn còn dương. Xem lại bài https://www.giaiphapexcel.com/diendan/threads/undocument-windows-api-và-vba.144002/post-933191.
Tui đã comment rất kỹ vào đó, dù đã có set obj = nothing, xuống 1, nhưng nó vẫn còn sống do nó được assign vào v nên reference counter nó lên 2 rồi xuống 1.
Cái tật đọc code và comment không kỹ, cứ lướt lướt :)
Bài đã được tự động gộp:

Tạm gác nó lại đi, code lấy VBA Dic counter đó các bạn đọc không hiểu đâu, chúng ta sẽ đi lại từ post 169. Giải thích rõ ràng cho các bạn hiểu về memory, DumpMem, VarPtr, ObjPtr, StrPtr.
Và tui sẽ viết thêm 2 hàm VBA không có là DWordPtr và VarIsNothing cho bé @thuyyeu99, và code hàm Đeo phai: Deophai_TypeName(const pv: POleVariant): AnsiString cho bài bên Delphi video kia.
 
Upvote 0
vậy là có Set Dic = ... thì bắt buột phải có Set Dic = nothing ???
nếu ko set Dic = nothing thì điều gỉ sẻ xẩy ra ???

Nếu obj được DIM trong Sub, Function khi chạy xong VBA tự Set obj = Nothing cho mình. Nhưng về khía cạnh lập trình developer nên chủ ý thực hiện việc này nó đẹp hơn và tường mình code hơn. Có New thì có Nothing. Trong Delphi có Create thì có Destroy từ obj.Free.
 
Upvote 0
Nếu obj được DIM trong Sub, Function khi chạy xong VBA tự Set obj = Nothing cho mình. Nhưng về khía cạnh lập trình developer nên chủ ý thực hiện việc này nó đẹp hơn và tường mình code hơn. Có New thì có Nothing. Trong Delphi có Create thì có Destroy từ obj.Free.
Vậy là ta khai báo như sau theo như Bạn đã chỉ cho Mạnh bên thớt Delphi Kia
Mã:
dic := TDictionary<string, TMyData>.create;
  try
    data := TMyData.Create;
    ....
    data.Free;
    end;
  finally
    dic.Free;
 
Upvote 0
Chà, sao tới lúc cần giải thích, viết dài thì mình cứ nổi cái bệnh lười lên ta ! Thôi ai hỏi gì nói đó cho rồi, tập trung vào post 167, 168, 169 nhen các bạn.
 
Upvote 0
Vậy là ta khai báo như sau theo như Bạn đã chỉ cho Mạnh bên thớt Delphi Kia
Mã:
dic := TDictionary<string, TMyData>.create;
  try
    data := TMyData.Create;
    ....
    data.Free;
    end;
  finally
    dic.Free;

Trong Delphi bạn làm thế là chuẩn đó, Nhưng viết lại rõ hơ nếu bạn nào mới học Delphi hiểu chắc chắn hơn là
Mã:
dic := TDictionary<string, TMyData>.create;
  try
    data := TMyData.Create;
    try
....
    finnaly
       data.Free;
    end;
  finally
    dic.Free;;
  end;

Quan trọng là nhớ việc Free khi chắc chắn không còn dùng đến hoặc mẹ của nó thoát. Lúc thì phải Free trong khối TRY..FINALLY, đôi khi Free trong khối mẹ của nó khi mẹ nó chạy OnDestroy.
 
Upvote 0
Chúng ta sẽ tiếp tục dùng DumpMem để xem reference count quyết định sự sống còn của 1 COM object nhé. Ở đây là object Dictionary. Và chúng ta cũng read trực tiếp từ bộ nhớ của 1 Dictionary object cái giá trị lưu cho property Count. Thú vị chút thôi nhé. Nhớ xem comment code và nhìn cho kỹ kết quả dump ra ở Immediate Windows.
Code này chạy cho Office 32bit nhé các bạn, Office 64 thì khác 1 chút, tui cần có scrrun.dll của Win64.
Mã:
Option Explicit

Public Sub Test_Dictionary()
    Dim obj As Object
    Dim v As Variant

#If VBA7 Then
    Dim lObjPtr As LongPtr
#Else
    Dim lObjPtr As Long
#End If
   
    Debug.Print "------- obj duoc khoi tao tu 1 class -------"
    Set obj = CreateObject("Scripting.Dictionary")  ' ref count = 1
    DumpMem VarPtr(obj), PTR_SIZE
    lObjPtr = ObjPtr(obj)
    Debug.Print "Pointer to the object instance of obj = " & Hex$(lObjPtr)
   
    DumpMem lObjPtr, PTR_SIZE   ' pointer to vtable
    DumpMem lObjPtr + 5 * PTR_SIZE, PTR_SIZE    ' ref count
   
    obj.Add 0, 1
    obj.Add 1, 2
    Debug.Print "Dictionary object có Count = " & obj.count
    DumpMem lObjPtr + 6 * PTR_SIZE, PTR_SIZE    ' dict count, read directly from memory

    Debug.Print "------- v duoc set = obj -------------------"
    Set v = obj     ' ref count = 2
    DumpVariant v
    DumpMem lObjPtr + 5 * PTR_SIZE, PTR_SIZE    ' ref count
    DumpMem lObjPtr + 6 * PTR_SIZE, PTR_SIZE    ' dict count
   
    Debug.Print "------- obj duoc set = nothing tro lai -----"
    Set obj = Nothing   ' ref count xuong còn 1
    DumpMem VarPtr(obj), PTR_SIZE
    DumpMem lObjPtr + 5 * PTR_SIZE, PTR_SIZE    ' ref count
    DumpMem lObjPtr + 6 * PTR_SIZE, PTR_SIZE    ' dict count

    Debug.Print "------- v van giu pointer to obj dict ------"
    DumpVariant v
   
    v.Add 2, 3
    v.Add 3, 4
   
    Debug.Print "Dictionary object có Count = " & v.count
    DumpMem lObjPtr + 6 * PTR_SIZE, PTR_SIZE    ' dict count, read directly from memory

    DumpVariant v
   
    Debug.Print "------- v = Empty, Erase obj dict ----------"
    v = Empty           ' ref count = 0, object dictionary duoc giai phóng (free)
    DumpVariant v
    DumpMem lObjPtr + 5 * PTR_SIZE, PTR_SIZE    ' ref count
    DumpMem lObjPtr + 6 * PTR_SIZE, PTR_SIZE    ' dict count

    ' v.Add 4, 5    ' <= die here
End Sub
 
Upvote 0
cái biết cái ko nhưng lúc rảnh cũng giáng học chút ... máy mạnh nó ra như sau
Mã:
------- obj duoc khoi tao tu 1 class -------
025AECF0: 58 4C B1 07
Pointer to the object instance of obj = 7B14C58
07B14C58: 1C 15 80 6D
07B14C6C: 01 00 00 00
Dictionary object có Count = 2
07B14C70: 02 00 00 00
------- v duoc set = obj -------------------
025AECE0: 09 00 00 00 00 00 00 00 58 4C B1 07 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 4C B1 07 00 00 00 00
07B14C6C: 02 00 00 00
07B14C70: 02 00 00 00
------- obj duoc set = nothing tro lai -----
025AECF0: 00 00 00 00
07B14C6C: 01 00 00 00
07B14C70: 02 00 00 00
------- v van giu pointer to obj dict ------
025AECE0: 09 00 00 00 00 00 00 00 58 4C B1 07 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 4C B1 07 00 00 00 00
Dictionary object có Count = 4
07B14C70: 04 00 00 00
025AECE0: 09 00 00 00 00 00 00 00 58 4C B1 07 00 00 00 00
VarType:
09 00
Reserved1-3:
00 00 00 00 00 00
Data:
58 4C B1 07 00 00 00 00
------- v = Empty, Erase obj dict ----------
025AECE0: 00 00 00 00 00 00 00 00 70 B3 77 0B 00 00 00 00
VarType:
00 00
Reserved1-3:
00 00 00 00 00 00
Data:
70 B3 77 0B 00 00 00 00
07B14C6C: 00 00 00 00
07B14C70: 00 00 00 00
 
Upvote 0
Đọc kỹ kết quả đi, xem hiểu gì không, nhất là code và comment
 
Upvote 0
Đừng quan tâm tới code, hãy để ý kỹ các con số. Tất cả mọi thứ trên máy tính chỉ đơn giản là con số địa chỉ và các byte values. Hiểu vậy và dùng DumpMem cho tất cả mọi thứ bạn nghĩ ra, các bạn sẽ thấy VBA nó đơn giản thế nào, ra sao.
 
Upvote 0
Object Dictionary đã được giải phóng, reference count của nó đã là 0 và count cũng đã là 0, tức mọi phần tử trong Items và Keys của nó đã được clear và giải phóng rồi, trả bộ nhớ về cho OS.
Gợi ý cậu Mạnh dòng đầu tiên nhé, rồi sẽ từ từ sáng ra:
Mã:
025AECF0: 58 4C B1 07
Tức biến obj có địa chỉ trên stack là &H025AECF0 (do biến khai báo trong hàm), nó chiếm 4 byte trên Win32 và 8 byte trên Win64. Giá trị của từng byte từ thấp đến cao là 58 4C B1 07, tức là 07B14C58 (=Long/LongPtr/DWord). Trên Win64 thì địa chỉ là 8 byte (tức 16 chử số Hex) và giá trị của nó cũng là 16 chữ số hex. 2 chử số Hex là 1 byte.
Vì hệ máy PC của chúng ta thuộc hệ "vợ bé" (Litle Endian) tức byte thấp đứng trước, byte lớn đứng sau, word thấp đứng trước, word lớn đứng sau, dword nhỏ đứng trước, dword lớn đứng sau. Nên khi đọc dãy hex, muốn đổi sang kiểu nào thì ta đổi từ phải sang trái, cao xuống thấp. Tức lật ngược lại đó.
Vd 58 4C B1 07 để biểu diễn cho 2 số Word thì nó sẽ là 4C58 và 07B1, nếu cho số DWord thì 07 B1 4C 58.
Hệ "vợ lớn" (Big Endian) thì ngược lại, lớn trước nhỏ sau, đọc từ trái qua phải sao thì số nó vậy.
VarPtr cho ta địa chỉ của 1 biến trong vùng nhớ. Hàm này không cách nào chúng ta tự viết được, phải dùng của VBA cho. Còn hai hàm StrPtr và ObjPtr thực ra đơn giản chỉ là lấy ra giá trị 4 (Win32) hay 8 byte (Win64) tại địa chỉ đó trả về cho ta.
Viết nôm na trong Delphi hay C/C++ thì
StrPtr := PDWord_Ptr(@1 biến string) ^;
ObjPtr := PDWord_Ptr(@1 biến obj)^;
Và:
VarPtr := @biến;

Mã:
025AECF0: 58 4C B1 07
Pointer to the object instance of obj = 7B14C58
07B14C58: 1C 15 80 6D
07B14C6C: 01 00 00 00
Dictionary object có Count = 2
07B14C70: 02 00 00 00
Cho nên cậu thấy ObjPtr(obj) = (0)7B14C58
Tại địa chỉ 07B14C58, chúng ta có giá trị quan trọng nhất quyết định mã chạy của 1 object, đó là con trỏ tới Virtual Method Table (VMT). Theo máy cậu lúc đó thì nó là 6D80151C (1C 15 80 6D), Nó trỏ tới 1 array of DWORD_PTR (4 byte 32, 8 byte 64), ngay phần tử đầu tiên của array. Mỗi phần tử trong array này chứa địa chỉ bắt đầu của 1 hàm trong bảng VMT của object. Tại địa chỉ đó chúng ta sẽ thấy mã máy của mov edi, edi hay push ebp, mov ebp, esp. Và cái chúng ta cần thử là đã có địa chỉ này rồi, làm sao gọi thẳng vào đó luôn.
Tại 07B14C6C, tức cách ObjPtr(obj) + 5 * 4 byte, chúng ta có 1 biến của obj, chiếm 4 byte, chính là số reference count, và nó là 01 00 00 00 tức = 1
Tại 07B14C70, tức cách ObjPtr(obj) + 6 * 4 byte, chúng ta có 1 biến nữa, chính là biến mà khi ta gọi property Count của Dictionary, nó sẽ lấy từ đây trả về cho chúng ta, đang là 02 00 00 00 tức = 2
2 biến này các bạn nhớ nhé, không phải object nào giống object nào, scrrun.dll nào giống scrrun.dll nào và Win32 khác Win64 nhé. Phải "rờ em" nó nhẹ nhàng thì nó mới phọt ra cho :)
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn tiếp tục với các dòng dưới
1 biến kiểu object được xem là Is Nothing khi ruột nó toàn 00. ObjPtr return 0.
1 biến kiểu string được xem là vbNullString khi ruột nó toàn 00. StrPtr return 0.
Trên VBA, chỉ có 2 biến kiểu pointer thôi là string (cả động và fix lengh) và object.
 
Lần chỉnh sửa cuối:
Upvote 0

Bài viết mới nhất

Back
Top Bottom